From b8c9d560dda747ee7de950344788a0ebec379ae5 Mon Sep 17 00:00:00 2001 From: Itzfebry Date: Thu, 17 Jul 2025 14:42:29 +0700 Subject: [PATCH] first commit backend --- .DS_Store | Bin 0 -> 10244 bytes .editorconfig | 18 + .gitattributes | 11 + .gitignore | 23 + app/Exports/QuizExport.php | 14 + app/Exports/RekapExport.php | 48 + app/Exports/TugasDetailExport.php | 107 + app/Exports/TugasExport.php | 100 + app/Http/Controllers/AdminController.php | 193 + app/Http/Controllers/Api/AuthController.php | 87 + app/Http/Controllers/Api/KelasContoller.php | 18 + .../Api/MataPelajaranController.php | 90 + app/Http/Controllers/Api/MateriController.php | 42 + .../Api/QuizAnalysisController.php | 67 + app/Http/Controllers/Api/QuizController.php | 222 + .../Controllers/Api/SubmitTugasController.php | 49 + .../Controllers/Api/TahunAjaranController.php | 19 + app/Http/Controllers/Api/TugasController.php | 47 + app/Http/Controllers/AuthController.php | 79 + app/Http/Controllers/Controller.php | 8 + app/Http/Controllers/DashboardController.php | 78 + app/Http/Controllers/GuruController.php | 160 + .../Controllers/GuruDashboardController.php | 27 + app/Http/Controllers/KelasContoller.php | 113 + .../Controllers/MataPelajaranController.php | 131 + .../Controllers/RoleGuru/MateriController.php | 232 + .../Controllers/RoleGuru/QuizController.php | 503 + .../RoleGuru/QuizRankingController.php | 62 + .../RoleGuru/RekapQuizController.php | 76 + .../RoleGuru/RekapTugasController.php | 161 + .../Controllers/RoleGuru/TugasController.php | 154 + app/Http/Controllers/SiswaController.php | 147 + .../Controllers/SiswaNotifikasiController.php | 51 + .../Controllers/TahunAjaranController.php | 115 + app/Http/Controllers/Traits/ApiResponse.php | 28 + app/Http/Controllers/UserController.php | 74 + app/Http/Controllers/WaliKelasController.php | 142 + app/Http/Middleware/CheckApiToken.php | 32 + app/Http/Middleware/RoleMiddleware.php | 26 + app/Http/Requests/ChangePasswordRequest.php | 17 + app/Http/Resources/SubmitTugasResource.php | 30 + app/Http/Resources/TugasResource.php | 31 + app/Imports/QuizImport.php | 21 + app/Models/Admin.php | 23 + app/Models/AuditLog.php | 18 + app/Models/Guru.php | 33 + app/Models/Kelas.php | 28 + app/Models/MataPelajaran.php | 34 + app/Models/Materi.php | 30 + app/Models/QuizAttemptAnswers.php | 27 + app/Models/QuizAttempts.php | 38 + app/Models/QuizLevelSetting.php | 24 + app/Models/QuizQuestions.php | 31 + app/Models/Quizzes.php | 39 + app/Models/Siswa.php | 40 + app/Models/SubmitTugas.php | 29 + app/Models/TahunAjaran.php | 15 + app/Models/Tugas.php | 38 + app/Models/User.php | 50 + app/Models/WaliKelas.php | 31 + app/Notifications/MateriBaruNotification.php | 37 + app/Notifications/QuizBaruNotification.php | 37 + app/Notifications/TugasBaruNotification.php | 38 + app/Providers/AppServiceProvider.php | 24 + app/Repositories/AdminRepository.php | 61 + app/Repositories/ApiSubmitTugasRepository.php | 99 + app/Repositories/ApiTugasRepository.php | 81 + app/Repositories/DashboardRepository.php | 73 + app/Repositories/GuruDashboardRepository.php | 243 + app/Repositories/GuruRepository.php | 60 + app/Repositories/KelasRepository.php | 47 + app/Repositories/MataPelajaranRepository.php | 64 + app/Repositories/MateriRepository.php | 115 + app/Repositories/QuizRepository.php | 219 + app/Repositories/SiswaRepository.php | 65 + app/Repositories/SubmitTugasRepository.php | 60 + app/Repositories/TahunAjaranRepository.php | 54 + app/Repositories/TugasRepository.php | 111 + app/Repositories/UserRepository.php | 42 + app/Repositories/WaliKelasRepository.php | 60 + app/View/Components/Icon.php | 26 + artisan | 15 + bootstrap/app.php | 21 + bootstrap/cache/.gitignore | 2 + bootstrap/providers.php | 5 + composer.json | 77 + composer.lock | 8832 +++++++++++++++++ config/app.php | 126 + config/auth.php | 115 + config/cache.php | 108 + config/database.php | 173 + config/excel.php | 380 + config/filesystems.php | 80 + config/logging.php | 132 + config/mail.php | 116 + config/queue.php | 112 + config/sanctum.php | 83 + config/services.php | 38 + config/session.php | 217 + config/sweetalert.php | 267 + database/.gitignore | 1 + database/factories/UserFactory.php | 44 + ...04_06_041010_create_tahun_ajaran_table.php | 27 + .../2025_04_06_041050_create_users_table.php | 29 + .../2025_04_06_041203_create_admin_table.php | 36 + .../2025_04_06_041210_create_guru_table.php | 36 + .../2025_04_06_041748_create_kelas_table.php | 33 + .../2025_04_06_042443_create_siswa_table.php | 50 + ...4_06_043020_create_matapelajaran_table.php | 48 + .../2025_04_06_043328_create_tugas_table.php | 50 + ...04_06_044101_create_submit_tugas_table.php | 43 + .../2025_04_06_044510_create_materi_table.php | 46 + ...025_04_07_020934_create_sessions_table.php | 30 + ...04_09_041911_update_column_kelas_table.php | 34 + ...4_09_042116_create_riwayat_kelas_table.php | 47 + ...04_13_040415_update_column_tugas_table.php | 33 + ...39_create_personal_access_tokens_table.php | 32 + ...000000_add_nilai_to_submit_tugas_table.php | 27 + ...2025_04_19_060119_create_quizzes_table.php | 37 + ..._19_060933_create_quiz_questions_table.php | 40 + ...4_19_061824_create_quiz_attempts_table.php | 42 + ...1836_create_quiz_attempt_answers_table.php | 42 + ...2025_04_28_123932_update_quizzes_table.php | 27 + ...ah_soal_dijawab_to_quiz_attempts_table.php | 30 + ...5_01_113324_create_notifications_table.php | 31 + ...35306_create_quiz_level_settings_table.php | 31 + ...5_17_041523_update_quiz_attempts_table.php | 33 + ..._17_083327_update_quiz_questions_table.php | 27 + ...5_17_112603_update_quiz_attempts_table.php | 27 + ...72836_update_quiz_level_settings_table.php | 27 + .../2025_05_25_065949_create_cache_tables.php | 35 + ...6_14_230738_add_waktu_to_quizzes_table.php | 28 + ...3329_add_timing_to_quiz_attempts_table.php | 28 + ..._08_191737_add_nip_wali_to_kelas_table.php | 21 + ...5_07_09_000000_create_audit_logs_table.php | 23 + ...5_update_tenggat_column_on_tugas_table.php | 28 + ...9_update_tenggat_column_on_tugas_table.php | 28 + ..._update_tanggal_column_on_materi_table.php | 28 + ...15_000000_add_deskripsi_to_tugas_table.php | 19 + database/seeders/AdminSeeder.php | 31 + database/seeders/DatabaseSeeder.php | 26 + database/seeders/KelasSeeder.php | 24 + database/seeders/TahunAjaranSeeder.php | 25 + package-lock.json | 3966 ++++++++ package.json | 22 + phpunit.xml | 33 + postcss.config.js | 6 + public/.DS_Store | Bin 0 -> 6148 bytes public/.htaccess | 25 + public/favicon.ico | 0 public/index.php | 17 + public/robots.txt | 2 + public/template/css/main.css | 1730 ++++ public/template/img/justboil-logo.svg | 3 + public/template/img/logo.png | Bin 0 -> 1271628 bytes public/template/img/logo2.png | Bin 0 -> 176808 bytes public/template/img/user.jpg | Bin 0 -> 6369 bytes public/template/img/wallpaperlogin.jpg | Bin 0 -> 569013 bytes public/template/js/chart.sample.js | 112 + public/template/js/chart.sample.min.js | 1 + public/template/js/main.js | 59 + public/template/js/main.min.js | 1 + public/vendor/sweetalert/sweetalert.all.js | 6 + resources/css/app.css | 3 + resources/js/app.js | 2 + resources/js/bootstrap.js | 4 + resources/views/components/icon.blade.php | 20 + resources/views/layouts/app.blade.php | 292 + .../pages/auth/change_password.blade.php | 194 + resources/views/pages/auth/index.blade.php | 171 + .../pages/role_admin/admin/create.blade.php | 68 + .../pages/role_admin/admin/edit.blade.php | 60 + .../pages/role_admin/admin/index.blade.php | 139 + .../admin_dashboard/index.blade.php | 479 + .../pages/role_admin/audit_log.blade.php | 41 + .../pages/role_admin/guru/create.blade.php | 68 + .../pages/role_admin/guru/edit.blade.php | 60 + .../pages/role_admin/guru/index.blade.php | 158 + .../role_admin/guru_dashboard/index.blade.php | 797 ++ .../pages/role_admin/kelas/create.blade.php | 36 + .../pages/role_admin/kelas/edit.blade.php | 38 + .../pages/role_admin/kelas/index.blade.php | 129 + .../mata_pelajaran/create.blade.php | 78 + .../role_admin/mata_pelajaran/edit.blade.php | 109 + .../role_admin/mata_pelajaran/index.blade.php | 105 + .../pages/role_admin/pindah_data.blade.php | 69 + .../pages/role_admin/siswa/create.blade.php | 100 + .../pages/role_admin/siswa/edit.blade.php | 102 + .../pages/role_admin/siswa/index.blade.php | 143 + .../role_admin/tahun_ajaran/create.blade.php | 59 + .../role_admin/tahun_ajaran/edit.blade.php | 46 + .../role_admin/tahun_ajaran/index.blade.php | 152 + .../role_admin/wali_kelas/create.blade.php | 91 + .../role_admin/wali_kelas/edit.blade.php | 96 + .../role_admin/wali_kelas/index.blade.php | 134 + .../pages/role_guru/dashboard/index.blade.php | 321 + .../pages/role_guru/materi/create.blade.php | 145 + .../pages/role_guru/materi/detail.blade.php | 74 + .../pages/role_guru/materi/edit.blade.php | 198 + .../pages/role_guru/materi/index.blade.php | 146 + .../pages/role_guru/quiz/create.blade.php | 678 ++ .../views/pages/role_guru/quiz/edit.blade.php | 123 + .../quiz/excel_export_quiz.blade.php | 48 + .../pages/role_guru/quiz/index.blade.php | 273 + .../pages/role_guru/quiz/rekap-quiz.blade.php | 201 + .../role_guru/rekap_tugas/detail.blade.php | 275 + .../role_guru/rekap_tugas/index.blade.php | 180 + .../pages/role_guru/tugas/create.blade.php | 108 + .../pages/role_guru/tugas/edit.blade.php | 112 + .../pages/role_guru/tugas/index.blade.php | 144 + resources/views/partials/footer.blade.php | 55 + resources/views/partials/navbar.blade.php | 143 + resources/views/partials/scripts.blade.php | 26 + resources/views/partials/sidebar.blade.php | 329 + .../views/vendor/sweetalert/alert.blade.php | 44 + resources/views/welcome.blade.php | 1 + routes/api.php | 81 + routes/console.php | 8 + routes/web.php | 148 + storage/.DS_Store | Bin 0 -> 6148 bytes storage/app/.gitignore | 4 + storage/app/private/.gitignore | 2 + storage/app/public/.gitignore | 2 + storage/framework/.gitignore | 9 + storage/framework/cache/.gitignore | 3 + storage/framework/cache/data/.gitignore | 2 + storage/framework/sessions/.gitignore | 2 + storage/framework/testing/.gitignore | 2 + storage/framework/views/.gitignore | 2 + storage/logs/.gitignore | 2 + tailwind.config.js | 20 + tests/Feature/ExampleTest.php | 19 + tests/TestCase.php | 10 + tests/Unit/ExampleTest.php | 16 + vite.config.js | 11 + 235 files changed, 32073 insertions(+) create mode 100644 .DS_Store create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 app/Exports/QuizExport.php create mode 100644 app/Exports/RekapExport.php create mode 100644 app/Exports/TugasDetailExport.php create mode 100644 app/Exports/TugasExport.php create mode 100644 app/Http/Controllers/AdminController.php create mode 100644 app/Http/Controllers/Api/AuthController.php create mode 100644 app/Http/Controllers/Api/KelasContoller.php create mode 100644 app/Http/Controllers/Api/MataPelajaranController.php create mode 100644 app/Http/Controllers/Api/MateriController.php create mode 100644 app/Http/Controllers/Api/QuizAnalysisController.php create mode 100644 app/Http/Controllers/Api/QuizController.php create mode 100644 app/Http/Controllers/Api/SubmitTugasController.php create mode 100644 app/Http/Controllers/Api/TahunAjaranController.php create mode 100644 app/Http/Controllers/Api/TugasController.php create mode 100644 app/Http/Controllers/AuthController.php create mode 100644 app/Http/Controllers/Controller.php create mode 100644 app/Http/Controllers/DashboardController.php create mode 100644 app/Http/Controllers/GuruController.php create mode 100644 app/Http/Controllers/GuruDashboardController.php create mode 100644 app/Http/Controllers/KelasContoller.php create mode 100644 app/Http/Controllers/MataPelajaranController.php create mode 100644 app/Http/Controllers/RoleGuru/MateriController.php create mode 100644 app/Http/Controllers/RoleGuru/QuizController.php create mode 100644 app/Http/Controllers/RoleGuru/QuizRankingController.php create mode 100644 app/Http/Controllers/RoleGuru/RekapQuizController.php create mode 100644 app/Http/Controllers/RoleGuru/RekapTugasController.php create mode 100644 app/Http/Controllers/RoleGuru/TugasController.php create mode 100644 app/Http/Controllers/SiswaController.php create mode 100644 app/Http/Controllers/SiswaNotifikasiController.php create mode 100644 app/Http/Controllers/TahunAjaranController.php create mode 100644 app/Http/Controllers/Traits/ApiResponse.php create mode 100644 app/Http/Controllers/UserController.php create mode 100644 app/Http/Controllers/WaliKelasController.php create mode 100644 app/Http/Middleware/CheckApiToken.php create mode 100644 app/Http/Middleware/RoleMiddleware.php create mode 100644 app/Http/Requests/ChangePasswordRequest.php create mode 100644 app/Http/Resources/SubmitTugasResource.php create mode 100644 app/Http/Resources/TugasResource.php create mode 100644 app/Imports/QuizImport.php create mode 100644 app/Models/Admin.php create mode 100644 app/Models/AuditLog.php create mode 100644 app/Models/Guru.php create mode 100644 app/Models/Kelas.php create mode 100644 app/Models/MataPelajaran.php create mode 100644 app/Models/Materi.php create mode 100644 app/Models/QuizAttemptAnswers.php create mode 100644 app/Models/QuizAttempts.php create mode 100644 app/Models/QuizLevelSetting.php create mode 100644 app/Models/QuizQuestions.php create mode 100644 app/Models/Quizzes.php create mode 100644 app/Models/Siswa.php create mode 100644 app/Models/SubmitTugas.php create mode 100644 app/Models/TahunAjaran.php create mode 100644 app/Models/Tugas.php create mode 100644 app/Models/User.php create mode 100644 app/Models/WaliKelas.php create mode 100644 app/Notifications/MateriBaruNotification.php create mode 100644 app/Notifications/QuizBaruNotification.php create mode 100644 app/Notifications/TugasBaruNotification.php create mode 100644 app/Providers/AppServiceProvider.php create mode 100644 app/Repositories/AdminRepository.php create mode 100644 app/Repositories/ApiSubmitTugasRepository.php create mode 100644 app/Repositories/ApiTugasRepository.php create mode 100644 app/Repositories/DashboardRepository.php create mode 100644 app/Repositories/GuruDashboardRepository.php create mode 100644 app/Repositories/GuruRepository.php create mode 100644 app/Repositories/KelasRepository.php create mode 100644 app/Repositories/MataPelajaranRepository.php create mode 100644 app/Repositories/MateriRepository.php create mode 100644 app/Repositories/QuizRepository.php create mode 100644 app/Repositories/SiswaRepository.php create mode 100644 app/Repositories/SubmitTugasRepository.php create mode 100644 app/Repositories/TahunAjaranRepository.php create mode 100644 app/Repositories/TugasRepository.php create mode 100644 app/Repositories/UserRepository.php create mode 100644 app/Repositories/WaliKelasRepository.php create mode 100644 app/View/Components/Icon.php create mode 100644 artisan create mode 100644 bootstrap/app.php create mode 100644 bootstrap/cache/.gitignore create mode 100644 bootstrap/providers.php create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 config/app.php create mode 100644 config/auth.php create mode 100644 config/cache.php create mode 100644 config/database.php create mode 100644 config/excel.php create mode 100644 config/filesystems.php create mode 100644 config/logging.php create mode 100644 config/mail.php create mode 100644 config/queue.php create mode 100644 config/sanctum.php create mode 100644 config/services.php create mode 100644 config/session.php create mode 100644 config/sweetalert.php create mode 100644 database/.gitignore create mode 100644 database/factories/UserFactory.php create mode 100644 database/migrations/2025_04_06_041010_create_tahun_ajaran_table.php create mode 100644 database/migrations/2025_04_06_041050_create_users_table.php create mode 100644 database/migrations/2025_04_06_041203_create_admin_table.php create mode 100644 database/migrations/2025_04_06_041210_create_guru_table.php create mode 100644 database/migrations/2025_04_06_041748_create_kelas_table.php create mode 100644 database/migrations/2025_04_06_042443_create_siswa_table.php create mode 100644 database/migrations/2025_04_06_043020_create_matapelajaran_table.php create mode 100644 database/migrations/2025_04_06_043328_create_tugas_table.php create mode 100644 database/migrations/2025_04_06_044101_create_submit_tugas_table.php create mode 100644 database/migrations/2025_04_06_044510_create_materi_table.php create mode 100644 database/migrations/2025_04_07_020934_create_sessions_table.php create mode 100644 database/migrations/2025_04_09_041911_update_column_kelas_table.php create mode 100644 database/migrations/2025_04_09_042116_create_riwayat_kelas_table.php create mode 100644 database/migrations/2025_04_13_040415_update_column_tugas_table.php create mode 100644 database/migrations/2025_04_13_090139_create_personal_access_tokens_table.php create mode 100644 database/migrations/2025_04_14_000000_add_nilai_to_submit_tugas_table.php create mode 100644 database/migrations/2025_04_19_060119_create_quizzes_table.php create mode 100644 database/migrations/2025_04_19_060933_create_quiz_questions_table.php create mode 100644 database/migrations/2025_04_19_061824_create_quiz_attempts_table.php create mode 100644 database/migrations/2025_04_19_061836_create_quiz_attempt_answers_table.php create mode 100644 database/migrations/2025_04_28_123932_update_quizzes_table.php create mode 100644 database/migrations/2025_04_29_025446_add_jumlah_soal_dijawab_to_quiz_attempts_table.php create mode 100644 database/migrations/2025_05_01_113324_create_notifications_table.php create mode 100644 database/migrations/2025_05_14_135306_create_quiz_level_settings_table.php create mode 100644 database/migrations/2025_05_17_041523_update_quiz_attempts_table.php create mode 100644 database/migrations/2025_05_17_083327_update_quiz_questions_table.php create mode 100644 database/migrations/2025_05_17_112603_update_quiz_attempts_table.php create mode 100644 database/migrations/2025_05_18_072836_update_quiz_level_settings_table.php create mode 100644 database/migrations/2025_05_25_065949_create_cache_tables.php create mode 100644 database/migrations/2025_06_14_230738_add_waktu_to_quizzes_table.php create mode 100644 database/migrations/2025_06_15_023329_add_timing_to_quiz_attempts_table.php create mode 100644 database/migrations/2025_07_08_191737_add_nip_wali_to_kelas_table.php create mode 100644 database/migrations/2025_07_09_000000_create_audit_logs_table.php create mode 100644 database/migrations/2025_07_09_032625_update_tenggat_column_on_tugas_table.php create mode 100644 database/migrations/2025_07_09_032819_update_tenggat_column_on_tugas_table.php create mode 100644 database/migrations/2025_07_09_035728_update_tanggal_column_on_materi_table.php create mode 100644 database/migrations/2025_07_15_000000_add_deskripsi_to_tugas_table.php create mode 100644 database/seeders/AdminSeeder.php create mode 100644 database/seeders/DatabaseSeeder.php create mode 100644 database/seeders/KelasSeeder.php create mode 100644 database/seeders/TahunAjaranSeeder.php create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 phpunit.xml create mode 100644 postcss.config.js create mode 100644 public/.DS_Store create mode 100644 public/.htaccess create mode 100644 public/favicon.ico create mode 100644 public/index.php create mode 100644 public/robots.txt create mode 100644 public/template/css/main.css create mode 100644 public/template/img/justboil-logo.svg create mode 100644 public/template/img/logo.png create mode 100644 public/template/img/logo2.png create mode 100644 public/template/img/user.jpg create mode 100644 public/template/img/wallpaperlogin.jpg create mode 100644 public/template/js/chart.sample.js create mode 100644 public/template/js/chart.sample.min.js create mode 100644 public/template/js/main.js create mode 100644 public/template/js/main.min.js create mode 100644 public/vendor/sweetalert/sweetalert.all.js create mode 100644 resources/css/app.css create mode 100644 resources/js/app.js create mode 100644 resources/js/bootstrap.js create mode 100644 resources/views/components/icon.blade.php create mode 100644 resources/views/layouts/app.blade.php create mode 100644 resources/views/pages/auth/change_password.blade.php create mode 100644 resources/views/pages/auth/index.blade.php create mode 100644 resources/views/pages/role_admin/admin/create.blade.php create mode 100644 resources/views/pages/role_admin/admin/edit.blade.php create mode 100644 resources/views/pages/role_admin/admin/index.blade.php create mode 100644 resources/views/pages/role_admin/admin_dashboard/index.blade.php create mode 100644 resources/views/pages/role_admin/audit_log.blade.php create mode 100644 resources/views/pages/role_admin/guru/create.blade.php create mode 100644 resources/views/pages/role_admin/guru/edit.blade.php create mode 100644 resources/views/pages/role_admin/guru/index.blade.php create mode 100644 resources/views/pages/role_admin/guru_dashboard/index.blade.php create mode 100644 resources/views/pages/role_admin/kelas/create.blade.php create mode 100644 resources/views/pages/role_admin/kelas/edit.blade.php create mode 100644 resources/views/pages/role_admin/kelas/index.blade.php create mode 100644 resources/views/pages/role_admin/mata_pelajaran/create.blade.php create mode 100644 resources/views/pages/role_admin/mata_pelajaran/edit.blade.php create mode 100644 resources/views/pages/role_admin/mata_pelajaran/index.blade.php create mode 100644 resources/views/pages/role_admin/pindah_data.blade.php create mode 100644 resources/views/pages/role_admin/siswa/create.blade.php create mode 100644 resources/views/pages/role_admin/siswa/edit.blade.php create mode 100644 resources/views/pages/role_admin/siswa/index.blade.php create mode 100644 resources/views/pages/role_admin/tahun_ajaran/create.blade.php create mode 100644 resources/views/pages/role_admin/tahun_ajaran/edit.blade.php create mode 100644 resources/views/pages/role_admin/tahun_ajaran/index.blade.php create mode 100644 resources/views/pages/role_admin/wali_kelas/create.blade.php create mode 100644 resources/views/pages/role_admin/wali_kelas/edit.blade.php create mode 100644 resources/views/pages/role_admin/wali_kelas/index.blade.php create mode 100644 resources/views/pages/role_guru/dashboard/index.blade.php create mode 100644 resources/views/pages/role_guru/materi/create.blade.php create mode 100644 resources/views/pages/role_guru/materi/detail.blade.php create mode 100644 resources/views/pages/role_guru/materi/edit.blade.php create mode 100644 resources/views/pages/role_guru/materi/index.blade.php create mode 100644 resources/views/pages/role_guru/quiz/create.blade.php create mode 100644 resources/views/pages/role_guru/quiz/edit.blade.php create mode 100644 resources/views/pages/role_guru/quiz/excel_export_quiz.blade.php create mode 100644 resources/views/pages/role_guru/quiz/index.blade.php create mode 100644 resources/views/pages/role_guru/quiz/rekap-quiz.blade.php create mode 100644 resources/views/pages/role_guru/rekap_tugas/detail.blade.php create mode 100644 resources/views/pages/role_guru/rekap_tugas/index.blade.php create mode 100644 resources/views/pages/role_guru/tugas/create.blade.php create mode 100644 resources/views/pages/role_guru/tugas/edit.blade.php create mode 100644 resources/views/pages/role_guru/tugas/index.blade.php create mode 100644 resources/views/partials/footer.blade.php create mode 100644 resources/views/partials/navbar.blade.php create mode 100644 resources/views/partials/scripts.blade.php create mode 100644 resources/views/partials/sidebar.blade.php create mode 100644 resources/views/vendor/sweetalert/alert.blade.php create mode 100644 resources/views/welcome.blade.php create mode 100644 routes/api.php create mode 100644 routes/console.php create mode 100644 routes/web.php create mode 100644 storage/.DS_Store create mode 100644 storage/app/.gitignore create mode 100644 storage/app/private/.gitignore create mode 100644 storage/app/public/.gitignore create mode 100644 storage/framework/.gitignore create mode 100644 storage/framework/cache/.gitignore create mode 100644 storage/framework/cache/data/.gitignore create mode 100644 storage/framework/sessions/.gitignore create mode 100644 storage/framework/testing/.gitignore create mode 100644 storage/framework/views/.gitignore create mode 100644 storage/logs/.gitignore create mode 100644 tailwind.config.js create mode 100644 tests/Feature/ExampleTest.php create mode 100644 tests/TestCase.php create mode 100644 tests/Unit/ExampleTest.php create mode 100644 vite.config.js diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..a7fbf64af3428b4b86efbe13f6bf27a7a85aa22b GIT binary patch literal 10244 zcmeHMO^91n6h1e}sg2O=n~(-~VU;wFt#MZuz`Sj0-2m!z3=Ufv6nmx(Zp zWaSSo-MA8~3pZi~v1oDS!iBC})J;(oH;RZ*>B5cro%?Q@dtctmxF}NO-r>G;^X_-f zJ?A_3CpSYxqBd%;5;;UvL}gjogGWN)ey(#Rqux9QDWFeYceUOM`hz*7ePJ1}3|Iy% z1C{~Hz>UHH&TKBlawP53GGH073|wP?_Xh`+WmU;ZB<0qDhr9wn=I~k;v@6_zbd;%fLJX ze0R^$GIgm(p>cn&d7tZj{a|g)^#T{~ioZYp<{cmY_T^EtzrC=3u&(_!a1NS8S!&XN z22XfFOIhZ{%T|~FmW4r6l;NBB{*zgc?%8J#etQ0^AEjr?dOw)?HQ#G^mHUXtE5NHw z3c<$^EkEYnc_4J}O5{?2zYypUdWgu>5O?mbVZ=tKu0SKft{x{4mu`Po#+itm#k?44 z#82-4OgB*r@$`|I05NqC(=we!D~NL;-T+$XB1zMOUW+zjoctNn%*!!-Is?|bCN|Su zgf*BG$mylNxcA*zcCrcA%(Jbqi7$8&hY zcM4ibHg*5eKh61^Eq#_R!WnU7O9F@(=U{4MKiCGy#{AXkiTAuq>t5oeED zCYEQZ*sIM_1FL6}@*5Z6nbEIj@7xzZT)Fs*T3sBY8c&~@X&60A*nhc{upP=c%GnP_@BM&>twrn6hKVZSb{x0mc>XTqUc=7BMy!xoR5Xi2qP8)YeYf&&thbw zU-y6OcJDXCW z*X{sv>SWJv2jf~W^4mkHTaP+QrDCa3xovxU<$!be@S&Xp&i2C(aQo1aot;wg*1Hcr z@@!+n>-)iL93o;6k;KVome=ty7L$>Sr(S(>9-(LB`F-`1$D?e-?CAMOM;RG;S~?fA zvsK^py};))lB2j8*=k~ydo;$=$6mhcZo&JFk;SEGhT<7J0eD|YLmIqL=4be#+0i*c z&vb5sO3YAmZpwY_Wn*8{u)4R|58nGDZcF#~nET9`Z+=oM zO0%J7Fb$*oytFF6UG9a?y!Ur@&kW(j6?zODvn`eZ%YbFzdN7cUj5uY;W9k3@zaB$b z8d=$wkpIy?1ML0Z1^*S)qsW@Q|6lv%8jMVDC;#*N|3BSyxd8wG literal 0 HcmV?d00001 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8f0de65 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +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 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fcb21d3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +* 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 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c7cf1fa --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +/.phpunit.cache +/node_modules +/public/build +/public/hot +/public/storage +/storage/*.key +/storage/pail +/vendor +.env +.env.backup +.env.production +.phpactor.json +.phpunit.result.cache +Homestead.json +Homestead.yaml +npm-debug.log +yarn-error.log +/auth.json +/.fleet +/.idea +/.nova +/.vscode +/.zed diff --git a/app/Exports/QuizExport.php b/app/Exports/QuizExport.php new file mode 100644 index 0000000..137bc9a --- /dev/null +++ b/app/Exports/QuizExport.php @@ -0,0 +1,14 @@ +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', + ]; + } +} diff --git a/app/Exports/TugasDetailExport.php b/app/Exports/TugasDetailExport.php new file mode 100644 index 0000000..c0f2fbe --- /dev/null +++ b/app/Exports/TugasDetailExport.php @@ -0,0 +1,107 @@ +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'] + ] + ] + ]; + } +} diff --git a/app/Exports/TugasExport.php b/app/Exports/TugasExport.php new file mode 100644 index 0000000..6442070 --- /dev/null +++ b/app/Exports/TugasExport.php @@ -0,0 +1,100 @@ +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'] + ] + ] + ]; + } +} diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php new file mode 100644 index 0000000..fbc3b96 --- /dev/null +++ b/app/Http/Controllers/AdminController.php @@ -0,0 +1,193 @@ +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')); + } +} diff --git a/app/Http/Controllers/Api/AuthController.php b/app/Http/Controllers/Api/AuthController.php new file mode 100644 index 0000000..d5dbc98 --- /dev/null +++ b/app/Http/Controllers/Api/AuthController.php @@ -0,0 +1,87 @@ +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, + ]); + + } +} diff --git a/app/Http/Controllers/Api/KelasContoller.php b/app/Http/Controllers/Api/KelasContoller.php new file mode 100644 index 0000000..cd4a27a --- /dev/null +++ b/app/Http/Controllers/Api/KelasContoller.php @@ -0,0 +1,18 @@ +get(); + return $this->okApiResponse($kelas); + } +} diff --git a/app/Http/Controllers/Api/MataPelajaranController.php b/app/Http/Controllers/Api/MataPelajaranController.php new file mode 100644 index 0000000..945ff9b --- /dev/null +++ b/app/Http/Controllers/Api/MataPelajaranController.php @@ -0,0 +1,90 @@ +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); + + } +} diff --git a/app/Http/Controllers/Api/MateriController.php b/app/Http/Controllers/Api/MateriController.php new file mode 100644 index 0000000..2b94a5e --- /dev/null +++ b/app/Http/Controllers/Api/MateriController.php @@ -0,0 +1,42 @@ +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()); + } + } +} diff --git a/app/Http/Controllers/Api/QuizAnalysisController.php b/app/Http/Controllers/Api/QuizAnalysisController.php new file mode 100644 index 0000000..0580616 --- /dev/null +++ b/app/Http/Controllers/Api/QuizAnalysisController.php @@ -0,0 +1,67 @@ +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()) + ]); + } + + +} diff --git a/app/Http/Controllers/Api/QuizController.php b/app/Http/Controllers/Api/QuizController.php new file mode 100644 index 0000000..cd389eb --- /dev/null +++ b/app/Http/Controllers/Api/QuizController.php @@ -0,0 +1,222 @@ +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 + ] + ]); + } +} diff --git a/app/Http/Controllers/Api/SubmitTugasController.php b/app/Http/Controllers/Api/SubmitTugasController.php new file mode 100644 index 0000000..a516e95 --- /dev/null +++ b/app/Http/Controllers/Api/SubmitTugasController.php @@ -0,0 +1,49 @@ +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"); + } +} diff --git a/app/Http/Controllers/Api/TahunAjaranController.php b/app/Http/Controllers/Api/TahunAjaranController.php new file mode 100644 index 0000000..033aac6 --- /dev/null +++ b/app/Http/Controllers/Api/TahunAjaranController.php @@ -0,0 +1,19 @@ +get(); + return $this->okApiResponse($data); + } +} diff --git a/app/Http/Controllers/Api/TugasController.php b/app/Http/Controllers/Api/TugasController.php new file mode 100644 index 0000000..475fd9e --- /dev/null +++ b/app/Http/Controllers/Api/TugasController.php @@ -0,0 +1,47 @@ +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); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php new file mode 100644 index 0000000..fb2fa64 --- /dev/null +++ b/app/Http/Controllers/AuthController.php @@ -0,0 +1,79 @@ +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()); + } + } +} diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php new file mode 100644 index 0000000..8677cd5 --- /dev/null +++ b/app/Http/Controllers/Controller.php @@ -0,0 +1,8 @@ +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) + { + // + } +} diff --git a/app/Http/Controllers/GuruController.php b/app/Http/Controllers/GuruController.php new file mode 100644 index 0000000..adebb47 --- /dev/null +++ b/app/Http/Controllers/GuruController.php @@ -0,0 +1,160 @@ +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(); + } + } +} diff --git a/app/Http/Controllers/GuruDashboardController.php b/app/Http/Controllers/GuruDashboardController.php new file mode 100644 index 0000000..f9c0e85 --- /dev/null +++ b/app/Http/Controllers/GuruDashboardController.php @@ -0,0 +1,27 @@ +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')); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/KelasContoller.php b/app/Http/Controllers/KelasContoller.php new file mode 100644 index 0000000..31ae1a6 --- /dev/null +++ b/app/Http/Controllers/KelasContoller.php @@ -0,0 +1,113 @@ +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(); + } + } +} diff --git a/app/Http/Controllers/MataPelajaranController.php b/app/Http/Controllers/MataPelajaranController.php new file mode 100644 index 0000000..18f6be9 --- /dev/null +++ b/app/Http/Controllers/MataPelajaranController.php @@ -0,0 +1,131 @@ +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) + { + // + } +} diff --git a/app/Http/Controllers/RoleGuru/MateriController.php b/app/Http/Controllers/RoleGuru/MateriController.php new file mode 100644 index 0000000..87ec147 --- /dev/null +++ b/app/Http/Controllers/RoleGuru/MateriController.php @@ -0,0 +1,232 @@ +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(); + } + } + +} diff --git a/app/Http/Controllers/RoleGuru/QuizController.php b/app/Http/Controllers/RoleGuru/QuizController.php new file mode 100644 index 0000000..cc6e81a --- /dev/null +++ b/app/Http/Controllers/RoleGuru/QuizController.php @@ -0,0 +1,503 @@ +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}).

POTENSI BUG: Jika tidak sama, siswa bisa stuck di level tertentu karena soal tidak cukup.
CATATAN: 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.

POTENSI BUG: Sistem akan stuck karena tidak ada cukup soal di level tersebut.
CATATAN: 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).

POTENSI BUG: Jika siswa salah satu saja, quiz akan stuck di level ini.
CATATAN: 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).

POTENSI BUG: Siswa tidak akan pernah naik level karena batas terlalu tinggi.
CATATAN: 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.

POTENSI BUG: Sistem akan stuck karena tidak ada soal di level tersebut.
CATATAN: 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).

POTENSI BUG: Sistem adaptive learning akan bingung dengan level yang tidak berurutan.
CATATAN: 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}).

POTENSI BUG: Quiz bisa stuck atau soal tidak cukup.
CATATAN: 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() + ]); + } + } +} diff --git a/app/Http/Controllers/RoleGuru/QuizRankingController.php b/app/Http/Controllers/RoleGuru/QuizRankingController.php new file mode 100644 index 0000000..f4e385d --- /dev/null +++ b/app/Http/Controllers/RoleGuru/QuizRankingController.php @@ -0,0 +1,62 @@ +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, + ]); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/RoleGuru/RekapQuizController.php b/app/Http/Controllers/RoleGuru/RekapQuizController.php new file mode 100644 index 0000000..e68054d --- /dev/null +++ b/app/Http/Controllers/RoleGuru/RekapQuizController.php @@ -0,0 +1,76 @@ +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'])); + } +} diff --git a/app/Http/Controllers/RoleGuru/RekapTugasController.php b/app/Http/Controllers/RoleGuru/RekapTugasController.php new file mode 100644 index 0000000..fc38258 --- /dev/null +++ b/app/Http/Controllers/RoleGuru/RekapTugasController.php @@ -0,0 +1,161 @@ +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 + ); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/RoleGuru/TugasController.php b/app/Http/Controllers/RoleGuru/TugasController.php new file mode 100644 index 0000000..aaf7c76 --- /dev/null +++ b/app/Http/Controllers/RoleGuru/TugasController.php @@ -0,0 +1,154 @@ +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(); + } + } +} diff --git a/app/Http/Controllers/SiswaController.php b/app/Http/Controllers/SiswaController.php new file mode 100644 index 0000000..8735f56 --- /dev/null +++ b/app/Http/Controllers/SiswaController.php @@ -0,0 +1,147 @@ +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(); + } + } +} diff --git a/app/Http/Controllers/SiswaNotifikasiController.php b/app/Http/Controllers/SiswaNotifikasiController.php new file mode 100644 index 0000000..833f619 --- /dev/null +++ b/app/Http/Controllers/SiswaNotifikasiController.php @@ -0,0 +1,51 @@ +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, + ]); + } +} diff --git a/app/Http/Controllers/TahunAjaranController.php b/app/Http/Controllers/TahunAjaranController.php new file mode 100644 index 0000000..f7e76ab --- /dev/null +++ b/app/Http/Controllers/TahunAjaranController.php @@ -0,0 +1,115 @@ +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(); + } + } +} diff --git a/app/Http/Controllers/Traits/ApiResponse.php b/app/Http/Controllers/Traits/ApiResponse.php new file mode 100644 index 0000000..6c968ec --- /dev/null +++ b/app/Http/Controllers/Traits/ApiResponse.php @@ -0,0 +1,28 @@ +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); + } +} diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php new file mode 100644 index 0000000..80a4e4f --- /dev/null +++ b/app/Http/Controllers/UserController.php @@ -0,0 +1,74 @@ +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(), + ]); + } + } +} diff --git a/app/Http/Controllers/WaliKelasController.php b/app/Http/Controllers/WaliKelasController.php new file mode 100644 index 0000000..ada6c40 --- /dev/null +++ b/app/Http/Controllers/WaliKelasController.php @@ -0,0 +1,142 @@ +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(); + } + } +} diff --git a/app/Http/Middleware/CheckApiToken.php b/app/Http/Middleware/CheckApiToken.php new file mode 100644 index 0000000..e498057 --- /dev/null +++ b/app/Http/Middleware/CheckApiToken.php @@ -0,0 +1,32 @@ +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); + } +} diff --git a/app/Http/Middleware/RoleMiddleware.php b/app/Http/Middleware/RoleMiddleware.php new file mode 100644 index 0000000..89bc6b9 --- /dev/null +++ b/app/Http/Middleware/RoleMiddleware.php @@ -0,0 +1,26 @@ +role, $roles)) { + return $next($request); + } + + abort(403, 'Unauthorized'); + } +} diff --git a/app/Http/Requests/ChangePasswordRequest.php b/app/Http/Requests/ChangePasswordRequest.php new file mode 100644 index 0000000..5482f50 --- /dev/null +++ b/app/Http/Requests/ChangePasswordRequest.php @@ -0,0 +1,17 @@ + ['required'], + 'new_password' => ['required', 'min:8', 'confirmed'], + ]; + } + +} diff --git a/app/Http/Resources/SubmitTugasResource.php b/app/Http/Resources/SubmitTugasResource.php new file mode 100644 index 0000000..7df3606 --- /dev/null +++ b/app/Http/Resources/SubmitTugasResource.php @@ -0,0 +1,30 @@ + $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, + ]; + }), + ]; + } +} \ No newline at end of file diff --git a/app/Http/Resources/TugasResource.php b/app/Http/Resources/TugasResource.php new file mode 100644 index 0000000..1802d4c --- /dev/null +++ b/app/Http/Resources/TugasResource.php @@ -0,0 +1,31 @@ + $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')), + ]; + } +} \ No newline at end of file diff --git a/app/Imports/QuizImport.php b/app/Imports/QuizImport.php new file mode 100644 index 0000000..89eeaa9 --- /dev/null +++ b/app/Imports/QuizImport.php @@ -0,0 +1,21 @@ +belongsTo(User::class, 'user_id', 'id'); + } +} diff --git a/app/Models/AuditLog.php b/app/Models/AuditLog.php new file mode 100644 index 0000000..bc8e668 --- /dev/null +++ b/app/Models/AuditLog.php @@ -0,0 +1,18 @@ +belongsTo(User::class, 'user_id', 'id'); + } +} \ No newline at end of file diff --git a/app/Models/Guru.php b/app/Models/Guru.php new file mode 100644 index 0000000..36ed82c --- /dev/null +++ b/app/Models/Guru.php @@ -0,0 +1,33 @@ +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'); + } +} diff --git a/app/Models/Kelas.php b/app/Models/Kelas.php new file mode 100644 index 0000000..055b5a8 --- /dev/null +++ b/app/Models/Kelas.php @@ -0,0 +1,28 @@ +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'); + } +} diff --git a/app/Models/MataPelajaran.php b/app/Models/MataPelajaran.php new file mode 100644 index 0000000..67c7df5 --- /dev/null +++ b/app/Models/MataPelajaran.php @@ -0,0 +1,34 @@ +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"); + } +} diff --git a/app/Models/Materi.php b/app/Models/Materi.php new file mode 100644 index 0000000..e91898a --- /dev/null +++ b/app/Models/Materi.php @@ -0,0 +1,30 @@ +belongsTo(MataPelajaran::class, "matapelajaran_id", "id"); + } + public function tahunAjaran() + { + return $this->belongsTo(TahunAjaran::class, "tahun_ajaran", "tahun"); + } +} diff --git a/app/Models/QuizAttemptAnswers.php b/app/Models/QuizAttemptAnswers.php new file mode 100644 index 0000000..2384943 --- /dev/null +++ b/app/Models/QuizAttemptAnswers.php @@ -0,0 +1,27 @@ +belongsTo(QuizAttempts::class, "attempt_id", "id"); + } + + public function quizQuestion() + { + return $this->belongsTo(QuizQuestions::class, "question_id", "id"); + } +} diff --git a/app/Models/QuizAttempts.php b/app/Models/QuizAttempts.php new file mode 100644 index 0000000..b24b904 --- /dev/null +++ b/app/Models/QuizAttempts.php @@ -0,0 +1,38 @@ +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"); + } +} diff --git a/app/Models/QuizLevelSetting.php b/app/Models/QuizLevelSetting.php new file mode 100644 index 0000000..cbdd38f --- /dev/null +++ b/app/Models/QuizLevelSetting.php @@ -0,0 +1,24 @@ +belongsTo(Quizzes::class); + } +} diff --git a/app/Models/QuizQuestions.php b/app/Models/QuizQuestions.php new file mode 100644 index 0000000..edea1b6 --- /dev/null +++ b/app/Models/QuizQuestions.php @@ -0,0 +1,31 @@ +hasMany(QuizAttemptAnswers::class, 'question_id'); + } + + public function quiz() + { + return $this->belongsTo(Quizzes::class, "quiz_id", "id"); + } +} diff --git a/app/Models/Quizzes.php b/app/Models/Quizzes.php new file mode 100644 index 0000000..ad219bb --- /dev/null +++ b/app/Models/Quizzes.php @@ -0,0 +1,39 @@ +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"); + } +} diff --git a/app/Models/Siswa.php b/app/Models/Siswa.php new file mode 100644 index 0000000..4b84e36 --- /dev/null +++ b/app/Models/Siswa.php @@ -0,0 +1,40 @@ +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"); + } +} diff --git a/app/Models/SubmitTugas.php b/app/Models/SubmitTugas.php new file mode 100644 index 0000000..3da702b --- /dev/null +++ b/app/Models/SubmitTugas.php @@ -0,0 +1,29 @@ +belongsTo(Siswa::class, "nisn", "nisn"); + } + public function tugas() + { + return $this->belongsTo(Tugas::class, "tugas_id", "id"); + } +} diff --git a/app/Models/TahunAjaran.php b/app/Models/TahunAjaran.php new file mode 100644 index 0000000..96913a3 --- /dev/null +++ b/app/Models/TahunAjaran.php @@ -0,0 +1,15 @@ +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"); + } +} diff --git a/app/Models/User.php b/app/Models/User.php new file mode 100644 index 0000000..6290fc4 --- /dev/null +++ b/app/Models/User.php @@ -0,0 +1,50 @@ + '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'); + } + +} diff --git a/app/Models/WaliKelas.php b/app/Models/WaliKelas.php new file mode 100644 index 0000000..6786d9a --- /dev/null +++ b/app/Models/WaliKelas.php @@ -0,0 +1,31 @@ +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'); + } +} diff --git a/app/Notifications/MateriBaruNotification.php b/app/Notifications/MateriBaruNotification.php new file mode 100644 index 0000000..87db61f --- /dev/null +++ b/app/Notifications/MateriBaruNotification.php @@ -0,0 +1,37 @@ +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, + ]; + } +} diff --git a/app/Notifications/QuizBaruNotification.php b/app/Notifications/QuizBaruNotification.php new file mode 100644 index 0000000..c8e61cd --- /dev/null +++ b/app/Notifications/QuizBaruNotification.php @@ -0,0 +1,37 @@ +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, + ]; + } +} diff --git a/app/Notifications/TugasBaruNotification.php b/app/Notifications/TugasBaruNotification.php new file mode 100644 index 0000000..a4a5d19 --- /dev/null +++ b/app/Notifications/TugasBaruNotification.php @@ -0,0 +1,38 @@ +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, + ]; + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php new file mode 100644 index 0000000..452e6b6 --- /dev/null +++ b/app/Providers/AppServiceProvider.php @@ -0,0 +1,24 @@ +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(); + } + +} \ No newline at end of file diff --git a/app/Repositories/ApiSubmitTugasRepository.php b/app/Repositories/ApiSubmitTugasRepository.php new file mode 100644 index 0000000..9700247 --- /dev/null +++ b/app/Repositories/ApiSubmitTugasRepository.php @@ -0,0 +1,99 @@ +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; + } +} \ No newline at end of file diff --git a/app/Repositories/ApiTugasRepository.php b/app/Repositories/ApiTugasRepository.php new file mode 100644 index 0000000..060b46d --- /dev/null +++ b/app/Repositories/ApiTugasRepository.php @@ -0,0 +1,81 @@ +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; + } +} \ No newline at end of file diff --git a/app/Repositories/DashboardRepository.php b/app/Repositories/DashboardRepository.php new file mode 100644 index 0000000..ed0e224 --- /dev/null +++ b/app/Repositories/DashboardRepository.php @@ -0,0 +1,73 @@ +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; + } +} \ No newline at end of file diff --git a/app/Repositories/GuruDashboardRepository.php b/app/Repositories/GuruDashboardRepository.php new file mode 100644 index 0000000..e109b74 --- /dev/null +++ b/app/Repositories/GuruDashboardRepository.php @@ -0,0 +1,243 @@ +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, + ], + ]; + } +} \ No newline at end of file diff --git a/app/Repositories/GuruRepository.php b/app/Repositories/GuruRepository.php new file mode 100644 index 0000000..2de9b64 --- /dev/null +++ b/app/Repositories/GuruRepository.php @@ -0,0 +1,60 @@ +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(); + } + +} \ No newline at end of file diff --git a/app/Repositories/KelasRepository.php b/app/Repositories/KelasRepository.php new file mode 100644 index 0000000..446d55e --- /dev/null +++ b/app/Repositories/KelasRepository.php @@ -0,0 +1,47 @@ +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(); + } + +} \ No newline at end of file diff --git a/app/Repositories/MataPelajaranRepository.php b/app/Repositories/MataPelajaranRepository.php new file mode 100644 index 0000000..9ae778c --- /dev/null +++ b/app/Repositories/MataPelajaranRepository.php @@ -0,0 +1,64 @@ +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(); + } + +} \ No newline at end of file diff --git a/app/Repositories/MateriRepository.php b/app/Repositories/MateriRepository.php new file mode 100644 index 0000000..a0b2478 --- /dev/null +++ b/app/Repositories/MateriRepository.php @@ -0,0 +1,115 @@ +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(); + } + +} \ No newline at end of file diff --git a/app/Repositories/QuizRepository.php b/app/Repositories/QuizRepository.php new file mode 100644 index 0000000..f953f4a --- /dev/null +++ b/app/Repositories/QuizRepository.php @@ -0,0 +1,219 @@ +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); + } +} \ No newline at end of file diff --git a/app/Repositories/SiswaRepository.php b/app/Repositories/SiswaRepository.php new file mode 100644 index 0000000..901dd93 --- /dev/null +++ b/app/Repositories/SiswaRepository.php @@ -0,0 +1,65 @@ +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(); + } + +} diff --git a/app/Repositories/SubmitTugasRepository.php b/app/Repositories/SubmitTugasRepository.php new file mode 100644 index 0000000..9a03123 --- /dev/null +++ b/app/Repositories/SubmitTugasRepository.php @@ -0,0 +1,60 @@ +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(); + } + +} \ No newline at end of file diff --git a/app/Repositories/TahunAjaranRepository.php b/app/Repositories/TahunAjaranRepository.php new file mode 100644 index 0000000..43ca410 --- /dev/null +++ b/app/Repositories/TahunAjaranRepository.php @@ -0,0 +1,54 @@ +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(); + } + +} \ No newline at end of file diff --git a/app/Repositories/TugasRepository.php b/app/Repositories/TugasRepository.php new file mode 100644 index 0000000..860c860 --- /dev/null +++ b/app/Repositories/TugasRepository.php @@ -0,0 +1,111 @@ +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(); + } + +} \ No newline at end of file diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php new file mode 100644 index 0000000..fd145c3 --- /dev/null +++ b/app/Repositories/UserRepository.php @@ -0,0 +1,42 @@ +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(); + } + +} \ No newline at end of file diff --git a/app/Repositories/WaliKelasRepository.php b/app/Repositories/WaliKelasRepository.php new file mode 100644 index 0000000..2f45c76 --- /dev/null +++ b/app/Repositories/WaliKelasRepository.php @@ -0,0 +1,60 @@ +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(); + } + +} \ No newline at end of file diff --git a/app/View/Components/Icon.php b/app/View/Components/Icon.php new file mode 100644 index 0000000..46197eb --- /dev/null +++ b/app/View/Components/Icon.php @@ -0,0 +1,26 @@ +handleCommand(new ArgvInput); + +exit($status); diff --git a/bootstrap/app.php b/bootstrap/app.php new file mode 100644 index 0000000..012ff0d --- /dev/null +++ b/bootstrap/app.php @@ -0,0 +1,21 @@ +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(); diff --git a/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/bootstrap/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/bootstrap/providers.php b/bootstrap/providers.php new file mode 100644 index 0000000..38b258d --- /dev/null +++ b/bootstrap/providers.php @@ -0,0 +1,5 @@ +=5.0.0" + }, + "require-dev": { + "doctrine/dbal": "^4.0.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2024-02-09T16:56:22+00:00" + }, + { + "name": "composer/pcre", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" + }, + "require-dev": { + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8 || ^9" + }, + "type": "library", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-11-12T16:29:46+00:00" + }, + { + "name": "composer/semver", + "version": "3.4.3", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.11", + "symfony/phpunit-bridge": "^3 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2024-09-19T14:15:21+00:00" + }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3" + }, + "time": "2024-07-08T12:26:09+00:00" + }, + { + "name": "doctrine/inflector", + "version": "2.0.10", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^11.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.3", + "phpunit/phpunit": "^8.5 || ^9.5", + "vimeo/psalm": "^4.25 || ^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.0.10" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2024-02-18T20:23:39+00:00" + }, + { + "name": "doctrine/lexer", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "doctrine/coding-standard": "^12", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^10.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^5.21" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/3.0.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2024-02-05T11:56:58+00:00" + }, + { + "name": "dragonmantank/cron-expression", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/dragonmantank/cron-expression.git", + "reference": "8c784d071debd117328803d86b2097615b457500" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "webmozart/assert": "^1.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Cron\\": "src/Cron/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chris Tankersley", + "email": "chris@ctankersley.com", + "homepage": "https://github.com/dragonmantank" + } + ], + "description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due", + "keywords": [ + "cron", + "schedule" + ], + "support": { + "issues": "https://github.com/dragonmantank/cron-expression/issues", + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" + }, + "funding": [ + { + "url": "https://github.com/dragonmantank", + "type": "github" + } + ], + "time": "2024-10-09T13:47:03+00:00" + }, + { + "name": "egulias/email-validator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/egulias/EmailValidator.git", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^2.0 || ^3.0", + "php": ">=8.1", + "symfony/polyfill-intl-idn": "^1.26" + }, + "require-dev": { + "phpunit/phpunit": "^10.2", + "vimeo/psalm": "^5.12" + }, + "suggest": { + "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Egulias\\EmailValidator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eduardo Gulias Davis" + } + ], + "description": "A library for validating emails against several RFCs", + "homepage": "https://github.com/egulias/EmailValidator", + "keywords": [ + "email", + "emailvalidation", + "emailvalidator", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/egulias/EmailValidator/issues", + "source": "https://github.com/egulias/EmailValidator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/egulias", + "type": "github" + } + ], + "time": "2025-03-06T22:45:56+00:00" + }, + { + "name": "ezyang/htmlpurifier", + "version": "v4.18.0", + "source": { + "type": "git", + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "cb56001e54359df7ae76dc522d08845dc741621b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b", + "reference": "cb56001e54359df7ae76dc522d08845dc741621b", + "shasum": "" + }, + "require": { + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + }, + "require-dev": { + "cerdic/css-tidy": "^1.7 || ^2.0", + "simpletest/simpletest": "dev-master" + }, + "suggest": { + "cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.", + "ext-bcmath": "Used for unit conversion and imagecrash protection", + "ext-iconv": "Converts text to and from non-UTF-8 encodings", + "ext-tidy": "Used for pretty-printing HTML" + }, + "type": "library", + "autoload": { + "files": [ + "library/HTMLPurifier.composer.php" + ], + "psr-0": { + "HTMLPurifier": "library/" + }, + "exclude-from-classmap": [ + "/library/HTMLPurifier/Language/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ], + "support": { + "issues": "https://github.com/ezyang/htmlpurifier/issues", + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0" + }, + "time": "2024-11-01T03:51:45+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b", + "reference": "3d158f36e7875e2f040f37bc0573956240a5a38b", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6|^7" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "support": { + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2023-10-12T05:21:21+00:00" + }, + { + "name": "graham-campbell/result-type", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", + "reference": "3ba905c11371512af9d9bdd27d99b782216b6945", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + }, + "type": "library", + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:45:45+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.9.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.3", + "guzzlehttp/psr7": "^2.7.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.9.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2025-03-27T13:37:11+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", + "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.2.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2025-03-27T13:27:01+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.7.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.39 || ^9.6.20" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.7.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2025-03-27T12:30:47+00:00" + }, + { + "name": "guzzlehttp/uri-template", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/guzzle/uri-template.git", + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/30e286560c137526eccd4ce21b2de477ab0676d2", + "reference": "30e286560c137526eccd4ce21b2de477ab0676d2", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "uri-template/tests": "1.0.0" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\UriTemplate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + } + ], + "description": "A polyfill class for uri_template of PHP", + "keywords": [ + "guzzlehttp", + "uri-template" + ], + "support": { + "issues": "https://github.com/guzzle/uri-template/issues", + "source": "https://github.com/guzzle/uri-template/tree/v1.0.4" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template", + "type": "tidelift" + } + ], + "time": "2025-02-03T10:55:03+00:00" + }, + { + "name": "laravel/framework", + "version": "v11.44.7", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "00bc6ac91a6d577bf051c18ddaa638c0d221e1c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/00bc6ac91a6d577bf051c18ddaa638c0d221e1c7", + "reference": "00bc6ac91a6d577bf051c18ddaa638c0d221e1c7", + "shasum": "" + }, + "require": { + "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", + "composer-runtime-api": "^2.2", + "doctrine/inflector": "^2.0.5", + "dragonmantank/cron-expression": "^3.4", + "egulias/email-validator": "^3.2.1|^4.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-hash": "*", + "ext-mbstring": "*", + "ext-openssl": "*", + "ext-session": "*", + "ext-tokenizer": "*", + "fruitcake/php-cors": "^1.3", + "guzzlehttp/guzzle": "^7.8.2", + "guzzlehttp/uri-template": "^1.0", + "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", + "laravel/serializable-closure": "^1.3|^2.0", + "league/commonmark": "^2.6", + "league/flysystem": "^3.25.1", + "league/flysystem-local": "^3.25.1", + "league/uri": "^7.5.1", + "monolog/monolog": "^3.0", + "nesbot/carbon": "^2.72.6|^3.8.4", + "nunomaduro/termwind": "^2.0", + "php": "^8.2", + "psr/container": "^1.1.1|^2.0.1", + "psr/log": "^1.0|^2.0|^3.0", + "psr/simple-cache": "^1.0|^2.0|^3.0", + "ramsey/uuid": "^4.7", + "symfony/console": "^7.0.3", + "symfony/error-handler": "^7.0.3", + "symfony/finder": "^7.0.3", + "symfony/http-foundation": "^7.2.0", + "symfony/http-kernel": "^7.0.3", + "symfony/mailer": "^7.0.3", + "symfony/mime": "^7.0.3", + "symfony/polyfill-php83": "^1.31", + "symfony/process": "^7.0.3", + "symfony/routing": "^7.0.3", + "symfony/uid": "^7.0.3", + "symfony/var-dumper": "^7.0.3", + "tijsverkoyen/css-to-inline-styles": "^2.2.5", + "vlucas/phpdotenv": "^5.6.1", + "voku/portable-ascii": "^2.0.2" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "provide": { + "psr/container-implementation": "1.1|2.0", + "psr/log-implementation": "1.0|2.0|3.0", + "psr/simple-cache-implementation": "1.0|2.0|3.0" + }, + "replace": { + "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", + "illuminate/bus": "self.version", + "illuminate/cache": "self.version", + "illuminate/collections": "self.version", + "illuminate/concurrency": "self.version", + "illuminate/conditionable": "self.version", + "illuminate/config": "self.version", + "illuminate/console": "self.version", + "illuminate/container": "self.version", + "illuminate/contracts": "self.version", + "illuminate/cookie": "self.version", + "illuminate/database": "self.version", + "illuminate/encryption": "self.version", + "illuminate/events": "self.version", + "illuminate/filesystem": "self.version", + "illuminate/hashing": "self.version", + "illuminate/http": "self.version", + "illuminate/log": "self.version", + "illuminate/macroable": "self.version", + "illuminate/mail": "self.version", + "illuminate/notifications": "self.version", + "illuminate/pagination": "self.version", + "illuminate/pipeline": "self.version", + "illuminate/process": "self.version", + "illuminate/queue": "self.version", + "illuminate/redis": "self.version", + "illuminate/routing": "self.version", + "illuminate/session": "self.version", + "illuminate/support": "self.version", + "illuminate/testing": "self.version", + "illuminate/translation": "self.version", + "illuminate/validation": "self.version", + "illuminate/view": "self.version", + "spatie/once": "*" + }, + "require-dev": { + "ably/ably-php": "^1.0", + "aws/aws-sdk-php": "^3.322.9", + "ext-gmp": "*", + "fakerphp/faker": "^1.24", + "guzzlehttp/promises": "^2.0.3", + "guzzlehttp/psr7": "^2.4", + "laravel/pint": "^1.18", + "league/flysystem-aws-s3-v3": "^3.25.1", + "league/flysystem-ftp": "^3.25.1", + "league/flysystem-path-prefixing": "^3.25.1", + "league/flysystem-read-only": "^3.25.1", + "league/flysystem-sftp-v3": "^3.25.1", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^9.11.2", + "pda/pheanstalk": "^5.0.6", + "php-http/discovery": "^1.15", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^10.5.35|^11.3.6|^12.0.1", + "predis/predis": "^2.3", + "resend/resend-php": "^0.10.0", + "symfony/cache": "^7.0.3", + "symfony/http-client": "^7.0.3", + "symfony/psr-http-message-bridge": "^7.0.3", + "symfony/translation": "^7.0.3" + }, + "suggest": { + "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).", + "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", + "ext-apcu": "Required to use the APC cache driver.", + "ext-fileinfo": "Required to use the Filesystem class.", + "ext-ftp": "Required to use the Flysystem FTP driver.", + "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", + "ext-memcached": "Required to use the memcache cache driver.", + "ext-pcntl": "Required to use all features of the queue worker and console signal trapping.", + "ext-pdo": "Required to use all database features.", + "ext-posix": "Required to use all features of the queue worker.", + "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0|^6.0).", + "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", + "filp/whoops": "Required for friendly error pages in development (^2.14.3).", + "laravel/tinker": "Required to use the tinker console command (^2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.25.1).", + "league/flysystem-read-only": "Required to use read-only disks (^3.25.1)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", + "mockery/mockery": "Required to use mocking (^1.6).", + "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", + "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", + "phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.3.6|^12.0.1).", + "predis/predis": "Required to use the predis connector (^2.3).", + "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", + "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^7.0).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^7.0).", + "symfony/http-client": "Required to enable support for the Symfony API mail transports (^7.0).", + "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^7.0).", + "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^7.0).", + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "11.x-dev" + } + }, + "autoload": { + "files": [ + "src/Illuminate/Collections/functions.php", + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", + "src/Illuminate/Filesystem/functions.php", + "src/Illuminate/Foundation/helpers.php", + "src/Illuminate/Log/functions.php", + "src/Illuminate/Support/functions.php", + "src/Illuminate/Support/helpers.php" + ], + "psr-4": { + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/", + "src/Illuminate/Conditionable/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Laravel Framework.", + "homepage": "https://laravel.com", + "keywords": [ + "framework", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2025-04-25T12:40:47+00:00" + }, + { + "name": "laravel/prompts", + "version": "v0.3.5", + "source": { + "type": "git", + "url": "https://github.com/laravel/prompts.git", + "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/prompts/zipball/57b8f7efe40333cdb925700891c7d7465325d3b1", + "reference": "57b8f7efe40333cdb925700891c7d7465325d3b1", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.2", + "ext-mbstring": "*", + "php": "^8.1", + "symfony/console": "^6.2|^7.0" + }, + "conflict": { + "illuminate/console": ">=10.17.0 <10.25.0", + "laravel/framework": ">=10.17.0 <10.25.0" + }, + "require-dev": { + "illuminate/collections": "^10.0|^11.0|^12.0", + "mockery/mockery": "^1.5", + "pestphp/pest": "^2.3|^3.4", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-mockery": "^1.1" + }, + "suggest": { + "ext-pcntl": "Required for the spinner to be animated." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "0.3.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Laravel\\Prompts\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Add beautiful and user-friendly forms to your command-line applications.", + "support": { + "issues": "https://github.com/laravel/prompts/issues", + "source": "https://github.com/laravel/prompts/tree/v0.3.5" + }, + "time": "2025-02-11T13:34:40+00:00" + }, + { + "name": "laravel/sanctum", + "version": "v4.1.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/sanctum.git", + "reference": "a360a6a1fd2400ead4eb9b6a9c1bb272939194f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/a360a6a1fd2400ead4eb9b6a9c1bb272939194f5", + "reference": "a360a6a1fd2400ead4eb9b6a9c1bb272939194f5", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^11.0|^12.0", + "illuminate/contracts": "^11.0|^12.0", + "illuminate/database": "^11.0|^12.0", + "illuminate/support": "^11.0|^12.0", + "php": "^8.2", + "symfony/console": "^7.0" + }, + "require-dev": { + "mockery/mockery": "^1.6", + "orchestra/testbench": "^9.0|^10.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Sanctum\\SanctumServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sanctum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.", + "keywords": [ + "auth", + "laravel", + "sanctum" + ], + "support": { + "issues": "https://github.com/laravel/sanctum/issues", + "source": "https://github.com/laravel/sanctum" + }, + "time": "2025-04-23T13:03:38+00:00" + }, + { + "name": "laravel/serializable-closure", + "version": "v2.0.4", + "source": { + "type": "git", + "url": "https://github.com/laravel/serializable-closure.git", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "reference": "b352cf0534aa1ae6b4d825d1e762e35d43f8a841", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "illuminate/support": "^10.0|^11.0|^12.0", + "nesbot/carbon": "^2.67|^3.0", + "pestphp/pest": "^2.36|^3.0", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^6.2.0|^7.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\SerializableClosure\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "nuno@laravel.com" + } + ], + "description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.", + "keywords": [ + "closure", + "laravel", + "serializable" + ], + "support": { + "issues": "https://github.com/laravel/serializable-closure/issues", + "source": "https://github.com/laravel/serializable-closure" + }, + "time": "2025-03-19T13:51:03+00:00" + }, + { + "name": "laravel/tinker", + "version": "v2.10.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/tinker.git", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/tinker/zipball/22177cc71807d38f2810c6204d8f7183d88a57d3", + "reference": "22177cc71807d38f2810c6204d8f7183d88a57d3", + "shasum": "" + }, + "require": { + "illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0", + "php": "^7.2.5|^8.0", + "psy/psysh": "^0.11.1|^0.12.0", + "symfony/var-dumper": "^4.3.4|^5.0|^6.0|^7.0" + }, + "require-dev": { + "mockery/mockery": "~1.3.3|^1.4.2", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^8.5.8|^9.3.3|^10.0" + }, + "suggest": { + "illuminate/database": "The Illuminate Database package (^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0)." + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Tinker\\TinkerServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Tinker\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Powerful REPL for the Laravel framework.", + "keywords": [ + "REPL", + "Tinker", + "laravel", + "psysh" + ], + "support": { + "issues": "https://github.com/laravel/tinker/issues", + "source": "https://github.com/laravel/tinker/tree/v2.10.1" + }, + "time": "2025-01-27T14:24:01+00:00" + }, + { + "name": "league/commonmark", + "version": "2.6.2", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "06c3b0bf2540338094575612f4a1778d0d2d5e94" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/06c3b0bf2540338094575612f4a1778d0d2d5e94", + "reference": "06c3b0bf2540338094575612f4a1778d0d2d5e94", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.31.1", + "commonmark/commonmark.js": "0.31.1", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0 | ^7.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0 || ^5.0.0" + }, + "suggest": { + "symfony/yaml": "v2.3+ required if using the Front Matter extension" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "League\\CommonMark\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", + "keywords": [ + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", + "markdown", + "md", + "parser" + ], + "support": { + "docs": "https://commonmark.thephpleague.com/", + "forum": "https://github.com/thephpleague/commonmark/discussions", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } + ], + "time": "2025-04-18T21:09:27+00:00" + }, + { + "name": "league/config", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/config.git", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "shasum": "" + }, + "require": { + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Config\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" + } + ], + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", + "keywords": [ + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], + "support": { + "docs": "https://config.thephpleague.com/", + "issues": "https://github.com/thephpleague/config/issues", + "rss": "https://github.com/thephpleague/config/releases.atom", + "source": "https://github.com/thephpleague/config" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + } + ], + "time": "2022-12-11T20:36:23+00:00" + }, + { + "name": "league/flysystem", + "version": "3.29.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319", + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319", + "shasum": "" + }, + "require": { + "league/flysystem-local": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "async-aws/core": "<1.19.0", + "async-aws/s3": "<1.14.0", + "aws/aws-sdk-php": "3.209.31 || 3.210.0", + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1", + "phpseclib/phpseclib": "3.0.15", + "symfony/http-client": "<5.2" + }, + "require-dev": { + "async-aws/s3": "^1.5 || ^2.0", + "async-aws/simple-s3": "^1.1 || ^2.0", + "aws/aws-sdk-php": "^3.295.10", + "composer/semver": "^3.0", + "ext-fileinfo": "*", + "ext-ftp": "*", + "ext-mongodb": "^1.3", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.5", + "google/cloud-storage": "^1.23", + "guzzlehttp/psr7": "^2.6", + "microsoft/azure-storage-blob": "^1.1", + "mongodb/mongodb": "^1.2", + "phpseclib/phpseclib": "^3.0.36", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.5.11|^10.0", + "sabre/dav": "^4.6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "File storage abstraction for PHP", + "keywords": [ + "WebDAV", + "aws", + "cloud", + "file", + "files", + "filesystem", + "filesystems", + "ftp", + "s3", + "sftp", + "storage" + ], + "support": { + "issues": "https://github.com/thephpleague/flysystem/issues", + "source": "https://github.com/thephpleague/flysystem/tree/3.29.1" + }, + "time": "2024-10-08T08:58:34+00:00" + }, + { + "name": "league/flysystem-local", + "version": "3.29.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-local.git", + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "reference": "e0e8d52ce4b2ed154148453d321e97c8e931bd27", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "league/flysystem": "^3.0.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Local\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Local filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "file", + "files", + "filesystem", + "local" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-local/tree/3.29.0" + }, + "time": "2024-08-09T21:24:39+00:00" + }, + { + "name": "league/mime-type-detection", + "version": "1.16.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/mime-type-detection.git", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9", + "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "phpstan/phpstan": "^0.12.68", + "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\MimeTypeDetection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "Mime-type detection for Flysystem", + "support": { + "issues": "https://github.com/thephpleague/mime-type-detection/issues", + "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0" + }, + "funding": [ + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2024-09-21T08:32:55+00:00" + }, + { + "name": "league/uri", + "version": "7.5.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri.git", + "reference": "81fb5145d2644324614cc532b28efd0215bda430" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", + "reference": "81fb5145d2644324614cc532b28efd0215bda430", + "shasum": "" + }, + "require": { + "league/uri-interfaces": "^7.5", + "php": "^8.1" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "league/uri-components": "Needed to easily manipulate URI objects components", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "uri-template", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri/tree/7.5.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:40:02+00:00" + }, + { + "name": "league/uri-interfaces", + "version": "7.5.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^8.1", + "psr/http-factory": "^1", + "psr/http-message": "^1.1 || ^2.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common interfaces and classes for URI representation and interaction", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:18:47+00:00" + }, + { + "name": "maatwebsite/excel", + "version": "3.1.64", + "source": { + "type": "git", + "url": "https://github.com/SpartnerNL/Laravel-Excel.git", + "reference": "e25d44a2d91da9179cd2d7fec952313548597a79" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/e25d44a2d91da9179cd2d7fec952313548597a79", + "reference": "e25d44a2d91da9179cd2d7fec952313548597a79", + "shasum": "" + }, + "require": { + "composer/semver": "^3.3", + "ext-json": "*", + "illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0", + "php": "^7.0||^8.0", + "phpoffice/phpspreadsheet": "^1.29.9", + "psr/simple-cache": "^1.0||^2.0||^3.0" + }, + "require-dev": { + "laravel/scout": "^7.0||^8.0||^9.0||^10.0", + "orchestra/testbench": "^6.0||^7.0||^8.0||^9.0||^10.0", + "predis/predis": "^1.1" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Excel": "Maatwebsite\\Excel\\Facades\\Excel" + }, + "providers": [ + "Maatwebsite\\Excel\\ExcelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Maatwebsite\\Excel\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Patrick Brouwers", + "email": "patrick@spartner.nl" + } + ], + "description": "Supercharged Excel exports and imports in Laravel", + "keywords": [ + "PHPExcel", + "batch", + "csv", + "excel", + "export", + "import", + "laravel", + "php", + "phpspreadsheet" + ], + "support": { + "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", + "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.64" + }, + "funding": [ + { + "url": "https://laravel-excel.com/commercial-support", + "type": "custom" + }, + { + "url": "https://github.com/patrickbrouwers", + "type": "github" + } + ], + "time": "2025-02-24T11:12:50+00:00" + }, + { + "name": "maennchen/zipstream-php", + "version": "3.1.2", + "source": { + "type": "git", + "url": "https://github.com/maennchen/ZipStream-PHP.git", + "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f", + "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-zlib": "*", + "php-64bit": "^8.2" + }, + "require-dev": { + "brianium/paratest": "^7.7", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^3.16", + "guzzlehttp/guzzle": "^7.5", + "mikey179/vfsstream": "^1.6", + "php-coveralls/php-coveralls": "^2.5", + "phpunit/phpunit": "^11.0", + "vimeo/psalm": "^6.0" + }, + "suggest": { + "guzzlehttp/psr7": "^2.4", + "psr/http-message": "^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "ZipStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paul Duncan", + "email": "pabs@pablotron.org" + }, + { + "name": "Jonatan Männchen", + "email": "jonatan@maennchen.ch" + }, + { + "name": "Jesse Donat", + "email": "donatj@gmail.com" + }, + { + "name": "András Kolesár", + "email": "kolesar@kolesar.hu" + } + ], + "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.", + "keywords": [ + "stream", + "zip" + ], + "support": { + "issues": "https://github.com/maennchen/ZipStream-PHP/issues", + "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2" + }, + "funding": [ + { + "url": "https://github.com/maennchen", + "type": "github" + } + ], + "time": "2025-01-27T12:07:53+00:00" + }, + { + "name": "markbaker/complex", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPComplex.git", + "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9", + "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "phpcompatibility/php-compatibility": "^9.3", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Complex\\": "classes/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@lange.demon.co.uk" + } + ], + "description": "PHP Class for working with complex numbers", + "homepage": "https://github.com/MarkBaker/PHPComplex", + "keywords": [ + "complex", + "mathematics" + ], + "support": { + "issues": "https://github.com/MarkBaker/PHPComplex/issues", + "source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2" + }, + "time": "2022-12-06T16:21:08+00:00" + }, + { + "name": "markbaker/matrix", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPMatrix.git", + "reference": "728434227fe21be27ff6d86621a1b13107a2562c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c", + "reference": "728434227fe21be27ff6d86621a1b13107a2562c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "phpcompatibility/php-compatibility": "^9.3", + "phpdocumentor/phpdocumentor": "2.*", + "phploc/phploc": "^4.0", + "phpmd/phpmd": "2.*", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0", + "sebastian/phpcpd": "^4.0", + "squizlabs/php_codesniffer": "^3.7" + }, + "type": "library", + "autoload": { + "psr-4": { + "Matrix\\": "classes/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@demon-angel.eu" + } + ], + "description": "PHP Class for working with matrices", + "homepage": "https://github.com/MarkBaker/PHPMatrix", + "keywords": [ + "mathematics", + "matrix", + "vector" + ], + "support": { + "issues": "https://github.com/MarkBaker/PHPMatrix/issues", + "source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1" + }, + "time": "2022-12-02T22:17:43+00:00" + }, + { + "name": "monolog/monolog", + "version": "3.9.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", + "predis/predis": "^1.1 || ^2", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.9.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2025-03-24T10:02:05+00:00" + }, + { + "name": "nesbot/carbon", + "version": "3.9.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon.git", + "reference": "6d16a8a015166fe54e22c042e0805c5363aef50d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/6d16a8a015166fe54e22c042e0805c5363aef50d", + "reference": "6d16a8a015166fe54e22c042e0805c5363aef50d", + "shasum": "" + }, + "require": { + "carbonphp/carbon-doctrine-types": "<100.0", + "ext-json": "*", + "php": "^8.1", + "psr/clock": "^1.0", + "symfony/clock": "^6.3 || ^7.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/translation": "^4.4.18 || ^5.2.1|| ^6.0 || ^7.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "doctrine/dbal": "^3.6.3 || ^4.0", + "doctrine/orm": "^2.15.2 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.57.2", + "kylekatarnls/multi-tester": "^2.5.3", + "ondrejmirtes/better-reflection": "^6.25.0.4", + "phpmd/phpmd": "^2.15.0", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan": "^1.11.2", + "phpunit/phpunit": "^10.5.20", + "squizlabs/php_codesniffer": "^3.9.0" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/CarbonPHP/carbon/issues", + "source": "https://github.com/CarbonPHP/carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2025-03-27T12:57:33+00:00" + }, + { + "name": "nette/schema", + "version": "v1.3.2", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d", + "shasum": "" + }, + "require": { + "nette/utils": "^4.0", + "php": "8.1 - 8.4" + }, + "require-dev": { + "nette/tester": "^2.5.2", + "phpstan/phpstan-nette": "^1.0", + "tracy/tracy": "^2.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "support": { + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.3.2" + }, + "time": "2024-10-06T23:10:23+00:00" + }, + { + "name": "nette/utils", + "version": "v4.0.6", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "ce708655043c7050eb050df361c5e313cf708309" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/ce708655043c7050eb050df361c5e313cf708309", + "reference": "ce708655043c7050eb050df361c5e313cf708309", + "shasum": "" + }, + "require": { + "php": "8.0 - 8.4" + }, + "conflict": { + "nette/finder": "<3", + "nette/schema": "<1.2.2" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "dev-master", + "nette/tester": "^2.5", + "phpstan/phpstan": "^1.0", + "tracy/tracy": "^2.9" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v4.0.6" + }, + "time": "2025-03-30T21:06:30+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.4.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + }, + "time": "2024-12-30T11:07:19+00:00" + }, + { + "name": "nunomaduro/termwind", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/termwind.git", + "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/52915afe6a1044e8b9cee1bcff836fb63acf9cda", + "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^8.2", + "symfony/console": "^7.1.8" + }, + "require-dev": { + "illuminate/console": "^11.33.2", + "laravel/pint": "^1.18.2", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0", + "phpstan/phpstan": "^1.12.11", + "phpstan/phpstan-strict-rules": "^1.6.1", + "symfony/var-dumper": "^7.1.8", + "thecodingmachine/phpstan-strict-rules": "^1.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Termwind\\Laravel\\TermwindServiceProvider" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "files": [ + "src/Functions.php" + ], + "psr-4": { + "Termwind\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Its like Tailwind CSS, but for the console.", + "keywords": [ + "cli", + "console", + "css", + "package", + "php", + "style" + ], + "support": { + "issues": "https://github.com/nunomaduro/termwind/issues", + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://github.com/xiCO2k", + "type": "github" + } + ], + "time": "2024-11-21T10:39:51+00:00" + }, + { + "name": "phpoffice/phpspreadsheet", + "version": "1.29.10", + "source": { + "type": "git", + "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", + "reference": "c80041b1628c4f18030407134fe88303661d4e4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/c80041b1628c4f18030407134fe88303661d4e4e", + "reference": "c80041b1628c4f18030407134fe88303661d4e4e", + "shasum": "" + }, + "require": { + "composer/pcre": "^1||^2||^3", + "ext-ctype": "*", + "ext-dom": "*", + "ext-fileinfo": "*", + "ext-gd": "*", + "ext-iconv": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-xml": "*", + "ext-xmlreader": "*", + "ext-xmlwriter": "*", + "ext-zip": "*", + "ext-zlib": "*", + "ezyang/htmlpurifier": "^4.15", + "maennchen/zipstream-php": "^2.1 || ^3.0", + "markbaker/complex": "^3.0", + "markbaker/matrix": "^3.0", + "php": "^7.4 || ^8.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-main", + "dompdf/dompdf": "^1.0 || ^2.0 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.2", + "mitoteam/jpgraph": "^10.3", + "mpdf/mpdf": "^8.1.1", + "phpcompatibility/php-compatibility": "^9.3", + "phpstan/phpstan": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^8.5 || ^9.0", + "squizlabs/php_codesniffer": "^3.7", + "tecnickcom/tcpdf": "^6.5" + }, + "suggest": { + "dompdf/dompdf": "Option for rendering PDF with PDF Writer", + "ext-intl": "PHP Internationalization Functions", + "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers", + "mpdf/mpdf": "Option for rendering PDF with PDF Writer", + "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maarten Balliauw", + "homepage": "https://blog.maartenballiauw.be" + }, + { + "name": "Mark Baker", + "homepage": "https://markbakeruk.net" + }, + { + "name": "Franck Lefevre", + "homepage": "https://rootslabs.net" + }, + { + "name": "Erik Tilt" + }, + { + "name": "Adrien Crivelli" + } + ], + "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", + "homepage": "https://github.com/PHPOffice/PhpSpreadsheet", + "keywords": [ + "OpenXML", + "excel", + "gnumeric", + "ods", + "php", + "spreadsheet", + "xls", + "xlsx" + ], + "support": { + "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.10" + }, + "time": "2025-02-08T02:56:14+00:00" + }, + { + "name": "phpoption/phpoption", + "version": "1.9.3", + "source": { + "type": "git", + "url": "https://github.com/schmittjoh/php-option.git", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/e3fac8b24f56113f7cb96af14958c0dd16330f54", + "reference": "e3fac8b24f56113f7cb96af14958c0dd16330f54", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOption\\": "src/PhpOption/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Johannes M. Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh" + }, + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + } + ], + "description": "Option Type for PHP", + "keywords": [ + "language", + "option", + "php", + "type" + ], + "support": { + "issues": "https://github.com/schmittjoh/php-option/issues", + "source": "https://github.com/schmittjoh/php-option/tree/1.9.3" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption", + "type": "tidelift" + } + ], + "time": "2024-07-20T21:41:07+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, + { + "name": "psy/psysh", + "version": "v0.12.8", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "85057ceedee50c49d4f6ecaff73ee96adb3b3625" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/85057ceedee50c49d4f6ecaff73ee96adb3b3625", + "reference": "85057ceedee50c49d4f6ecaff73ee96adb3b3625", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^5.0 || ^4.0", + "php": "^8.0 || ^7.4", + "symfony/console": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^7.0 || ^6.0 || ^5.0 || ^4.0 || ^3.4" + }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": false, + "forward-command": false + }, + "branch-alias": { + "dev-main": "0.12.x-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.12.8" + }, + "time": "2025-03-16T03:05:19+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "ramsey/collection", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/collection.git", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2", + "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2", + "shasum": "" + }, + "require": { + "php": "^8.1" + }, + "require-dev": { + "captainhook/plugin-composer": "^5.3", + "ergebnis/composer-normalize": "^2.45", + "fakerphp/faker": "^1.24", + "hamcrest/hamcrest-php": "^2.0", + "jangregor/phpstan-prophecy": "^2.1", + "mockery/mockery": "^1.6", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpspec/prophecy-phpunit": "^2.3", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^10.5", + "ramsey/coding-standard": "^2.3", + "ramsey/conventional-commits": "^1.6", + "roave/security-advisories": "dev-latest" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Collection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "A PHP library for representing and manipulating collections.", + "keywords": [ + "array", + "collection", + "hash", + "map", + "queue", + "set" + ], + "support": { + "issues": "https://github.com/ramsey/collection/issues", + "source": "https://github.com/ramsey/collection/tree/2.1.1" + }, + "time": "2025-03-22T05:38:12+00:00" + }, + { + "name": "ramsey/uuid", + "version": "4.7.6", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", + "reference": "91039bc1faa45ba123c4328958e620d382ec7088", + "shasum": "" + }, + "require": { + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", + "ext-json": "*", + "php": "^8.0", + "ramsey/collection": "^1.2 || ^2.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "captainhook/captainhook": "^5.10", + "captainhook/plugin-composer": "^5.3", + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "doctrine/annotations": "^1.8", + "ergebnis/composer-normalize": "^2.15", + "mockery/mockery": "^1.3", + "paragonie/random-lib": "^2", + "php-mock/php-mock": "^2.2", + "php-mock/php-mock-mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.1", + "phpbench/phpbench": "^1.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^8.5 || ^9", + "ramsey/composer-repl": "^1.4", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.9" + }, + "suggest": { + "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", + "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.", + "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.", + "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "support": { + "issues": "https://github.com/ramsey/uuid/issues", + "source": "https://github.com/ramsey/uuid/tree/4.7.6" + }, + "funding": [ + { + "url": "https://github.com/ramsey", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", + "type": "tidelift" + } + ], + "time": "2024-04-27T21:32:50+00:00" + }, + { + "name": "realrashid/sweet-alert", + "version": "v7.3.0", + "source": { + "type": "git", + "url": "https://github.com/realrashid/sweet-alert.git", + "reference": "d54b1663970da8d416eb09e8719a8561a45fb2d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/realrashid/sweet-alert/zipball/d54b1663970da8d416eb09e8719a8561a45fb2d9", + "reference": "d54b1663970da8d416eb09e8719a8561a45fb2d9", + "shasum": "" + }, + "require": { + "laravel/framework": "^5.6|^6.0|^7.0|^8.0|^9.0|^9.11|9.14.*|^10.0|^11.0|^12.0", + "php": "^7.2|^8.0|^8.1|^8.2|^8.3" + }, + "require-dev": { + "symfony/thanks": "^1.0" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Alert": "RealRashid\\SweetAlert\\Facades\\Alert" + }, + "providers": [ + "RealRashid\\SweetAlert\\SweetAlertServiceProvider" + ] + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "RealRashid\\SweetAlert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Rashid Ali", + "email": "realrashid05@gmail.com", + "homepage": "https://realrashid.com", + "role": "Developer" + } + ], + "description": "Laravel Sweet Alert Is A Package For Laravel Provides An Easy Way To Display Alert Messages Using The SweetAlert2 Library.", + "homepage": "https://github.com/realrashid/sweet-alert", + "keywords": [ + "alert", + "laravel", + "laravel-package", + "notifier", + "noty", + "sweet-alert", + "sweet-alert2", + "toast" + ], + "support": { + "docs": "https://realrashid.github.io/sweet-alert/", + "email": "realrashid05@gmail.com", + "issues": "https://github.com/realrashid/sweet-alert/issues", + "source": "https://github.com/realrashid/sweet-alert" + }, + "funding": [ + { + "url": "https://ko-fi.com/realrashid", + "type": "custom" + }, + { + "url": "https://www.buymeacoffee.com/realrashid", + "type": "custom" + }, + { + "url": "https://issuehunt.io/r/realrashid", + "type": "issuehunt" + }, + { + "url": "https://tidelift.com/funding/github/packagist/realrashid/sweet-alert", + "type": "tidelift" + } + ], + "time": "2025-02-25T21:11:49+00:00" + }, + { + "name": "symfony/clock", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/clock.git", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/clock": "^1.0", + "symfony/polyfill-php83": "^1.28" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/now.php" + ], + "psr-4": { + "Symfony\\Component\\Clock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Decouples applications from the system clock", + "homepage": "https://symfony.com", + "keywords": [ + "clock", + "psr20", + "time" + ], + "support": { + "source": "https://github.com/symfony/clock/tree/v7.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/console", + "version": "v7.2.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "e51498ea18570c062e7df29d05a7003585b19b88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/e51498ea18570c062e7df29d05a7003585b19b88", + "reference": "e51498ea18570c062e7df29d05a7003585b19b88", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^6.4|^7.0" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v7.2.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-03-12T08:11:12+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v7.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/error-handler", + "version": "v7.2.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/error-handler.git", + "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b", + "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/var-dumper": "^6.4|^7.0" + }, + "conflict": { + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0" + }, + "bin": [ + "Resources/bin/patch-type-declarations" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\ErrorHandler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to manage errors and ease debugging PHP code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/error-handler/tree/v7.2.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-03-03T07:12:39+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/event-dispatcher-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/dependency-injection": "<6.4", + "symfony/service-contracts": "<2.5" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/error-handler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/finder", + "version": "v7.2.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "87a71856f2f56e4100373e92529eed3171695cfb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", + "reference": "87a71856f2f56e4100373e92529eed3171695cfb", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "symfony/filesystem": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v7.2.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-30T19:00:17+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v7.2.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "371272aeb6286f8135e028ca535f8e4d6f114126" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/371272aeb6286f8135e028ca535f8e4d6f114126", + "reference": "371272aeb6286f8135e028ca535f8e4d6f114126", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php83": "^1.27" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" + }, + "require-dev": { + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0", + "symfony/cache": "^6.4.12|^7.1.5", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v7.2.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-03-25T15:54:33+00:00" + }, + { + "name": "symfony/http-kernel", + "version": "v7.2.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-kernel.git", + "reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b1fe91bc1fa454a806d3f98db4ba826eb9941a54", + "reference": "b1fe91bc1fa454a806d3f98db4ba826eb9941a54", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/browser-kit": "<6.4", + "symfony/cache": "<6.4", + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/doctrine-bridge": "<6.4", + "symfony/form": "<6.4", + "symfony/http-client": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/mailer": "<6.4", + "symfony/messenger": "<6.4", + "symfony/translation": "<6.4", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<6.4", + "symfony/validator": "<6.4", + "symfony/var-dumper": "<6.4", + "twig/twig": "<3.12" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/clock": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/css-selector": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^7.1", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^7.1", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3", + "symfony/uid": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", + "symfony/var-exporter": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpKernel\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a structured process for converting a Request into a Response", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-kernel/tree/v7.2.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-03-28T13:32:50+00:00" + }, + { + "name": "symfony/mailer", + "version": "v7.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailer.git", + "reference": "f3871b182c44997cf039f3b462af4a48fb85f9d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailer/zipball/f3871b182c44997cf039f3b462af4a48fb85f9d3", + "reference": "f3871b182c44997cf039f3b462af4a48fb85f9d3", + "shasum": "" + }, + "require": { + "egulias/email-validator": "^2.1.10|^3|^4", + "php": ">=8.2", + "psr/event-dispatcher": "^1", + "psr/log": "^1|^2|^3", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/mime": "^7.2", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/messenger": "<6.4", + "symfony/mime": "<6.4", + "symfony/twig-bridge": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/twig-bridge": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps sending emails", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailer/tree/v7.2.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-27T11:08:17+00:00" + }, + { + "name": "symfony/mime", + "version": "v7.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "87ca22046b78c3feaff04b337f33b38510fd686b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/87ca22046b78c3feaff04b337f33b38510fd686b", + "reference": "87ca22046b78c3feaff04b337f33b38510fd686b", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<6.4", + "symfony/serializer": "<6.4.3|>7.0,<7.0.3" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/property-info": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v7.2.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-02-19T08:51:20+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", + "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php83", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php83\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/process", + "version": "v7.2.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "87b7c93e57df9d8e39a093d32587702380ff045d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d", + "reference": "87b7c93e57df9d8e39a093d32587702380ff045d", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v7.2.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-03-13T12:21:46+00:00" + }, + { + "name": "symfony/routing", + "version": "v7.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "ee9a67edc6baa33e5fae662f94f91fd262930996" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/ee9a67edc6baa33e5fae662f94f91fd262930996", + "reference": "ee9a67edc6baa33e5fae662f94f91fd262930996", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/config": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/yaml": "<6.4" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/expression-language": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Maps an HTTP request to a set of configuration variables", + "homepage": "https://symfony.com", + "keywords": [ + "router", + "routing", + "uri", + "url" + ], + "support": { + "source": "https://github.com/symfony/routing/tree/v7.2.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-17T10:56:55+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/string", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v7.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-11-13T13:31:26+00:00" + }, + { + "name": "symfony/translation", + "version": "v7.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "283856e6981286cc0d800b53bd5703e8e363f05a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/283856e6981286cc0d800b53bd5703e8e363f05a", + "reference": "283856e6981286cc0d800b53bd5703e8e363f05a", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.5|^3.0" + }, + "conflict": { + "symfony/config": "<6.4", + "symfony/console": "<6.4", + "symfony/dependency-injection": "<6.4", + "symfony/http-client-contracts": "<2.5", + "symfony/http-kernel": "<6.4", + "symfony/service-contracts": "<2.5", + "symfony/twig-bundle": "<6.4", + "symfony/yaml": "<6.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "nikic/php-parser": "^4.18|^5.0", + "psr/log": "^1|^2|^3", + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/finder": "^6.4|^7.0", + "symfony/http-client-contracts": "^2.5|^3.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/yaml": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v7.2.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-02-13T10:27:23+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" + }, + { + "name": "symfony/uid", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "2d294d0c48df244c71c105a169d0190bfb080426" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/2d294d0c48df244c71c105a169d0190bfb080426", + "reference": "2d294d0c48df244c71c105a169d0190bfb080426", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/tree/v7.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:21:43+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v7.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "82b478c69745d8878eb60f9a049a4d584996f73a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/82b478c69745d8878eb60f9a049a4d584996f73a", + "reference": "82b478c69745d8878eb60f9a049a4d584996f73a", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.12" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v7.2.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-17T11:39:41+00:00" + }, + { + "name": "tijsverkoyen/css-to-inline-styles", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "^7.4 || ^8.0", + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^8.5.21 || ^9.5.10" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "TijsVerkoyen\\CssToInlineStyles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Tijs Verkoyen", + "email": "css_to_inline_styles@verkoyen.eu", + "role": "Developer" + } + ], + "description": "CssToInlineStyles is a class that enables you to convert HTML-pages/files into HTML-pages/files with inline styles. This is very useful when you're sending emails.", + "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", + "support": { + "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0" + }, + "time": "2024-12-21T16:25:41+00:00" + }, + { + "name": "vlucas/phpdotenv", + "version": "v5.6.2", + "source": { + "type": "git", + "url": "https://github.com/vlucas/phpdotenv.git", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", + "shasum": "" + }, + "require": { + "ext-pcre": "*", + "graham-campbell/result-type": "^1.1.3", + "php": "^7.2.5 || ^8.0", + "phpoption/phpoption": "^1.9.3", + "symfony/polyfill-ctype": "^1.24", + "symfony/polyfill-mbstring": "^1.24", + "symfony/polyfill-php80": "^1.24" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-filter": "*", + "phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2" + }, + "suggest": { + "ext-filter": "Required to use the boolean validator." + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + }, + "branch-alias": { + "dev-master": "5.6-dev" + } + }, + "autoload": { + "psr-4": { + "Dotenv\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Vance Lucas", + "email": "vance@vancelucas.com", + "homepage": "https://github.com/vlucas" + } + ], + "description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.", + "keywords": [ + "dotenv", + "env", + "environment" + ], + "support": { + "issues": "https://github.com/vlucas/phpdotenv/issues", + "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], + "time": "2025-04-30T23:37:27+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "shasum": "" + }, + "require": { + "php": ">=7.0.0" + }, + "require-dev": { + "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "https://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2024-11-21T01:49:47+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "packages-dev": [ + { + "name": "fakerphp/faker", + "version": "v1.24.1", + "source": { + "type": "git", + "url": "https://github.com/FakerPHP/Faker.git", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "psr/container": "^1.0 || ^2.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "conflict": { + "fzaninotto/faker": "*" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "doctrine/persistence": "^1.3 || ^2.0", + "ext-intl": "*", + "phpunit/phpunit": "^9.5.26", + "symfony/phpunit-bridge": "^5.4.16" + }, + "suggest": { + "doctrine/orm": "Required to use Faker\\ORM\\Doctrine", + "ext-curl": "Required by Faker\\Provider\\Image to download images.", + "ext-dom": "Required by Faker\\Provider\\HtmlLorem for generating random HTML.", + "ext-iconv": "Required by Faker\\Provider\\ru_RU\\Text::realText() for generating real Russian text.", + "ext-mbstring": "Required for multibyte Unicode string functionality." + }, + "type": "library", + "autoload": { + "psr-4": { + "Faker\\": "src/Faker/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "François Zaninotto" + } + ], + "description": "Faker is a PHP library that generates fake data for you.", + "keywords": [ + "data", + "faker", + "fixtures" + ], + "support": { + "issues": "https://github.com/FakerPHP/Faker/issues", + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" + }, + "time": "2024-11-21T13:46:39+00:00" + }, + { + "name": "filp/whoops", + "version": "2.18.0", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e", + "reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Whoops\\": "src/Whoops/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", + "keywords": [ + "error", + "exception", + "handling", + "library", + "throwable", + "whoops" + ], + "support": { + "issues": "https://github.com/filp/whoops/issues", + "source": "https://github.com/filp/whoops/tree/2.18.0" + }, + "funding": [ + { + "url": "https://github.com/denis-sokolov", + "type": "github" + } + ], + "time": "2025-03-15T12:00:00+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "reference": "f8b1c0173b22fa6ec77a81fe63e5b01eba7e6487", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0 || ^3.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.1.1" + }, + "time": "2025-04-30T06:54:44+00:00" + }, + { + "name": "laravel/pail", + "version": "v1.2.2", + "source": { + "type": "git", + "url": "https://github.com/laravel/pail.git", + "reference": "f31f4980f52be17c4667f3eafe034e6826787db2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pail/zipball/f31f4980f52be17c4667f3eafe034e6826787db2", + "reference": "f31f4980f52be17c4667f3eafe034e6826787db2", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "illuminate/console": "^10.24|^11.0|^12.0", + "illuminate/contracts": "^10.24|^11.0|^12.0", + "illuminate/log": "^10.24|^11.0|^12.0", + "illuminate/process": "^10.24|^11.0|^12.0", + "illuminate/support": "^10.24|^11.0|^12.0", + "nunomaduro/termwind": "^1.15|^2.0", + "php": "^8.2", + "symfony/console": "^6.0|^7.0" + }, + "require-dev": { + "laravel/framework": "^10.24|^11.0|^12.0", + "laravel/pint": "^1.13", + "orchestra/testbench-core": "^8.13|^9.0|^10.0", + "pestphp/pest": "^2.20|^3.0", + "pestphp/pest-plugin-type-coverage": "^2.3|^3.0", + "phpstan/phpstan": "^1.10", + "symfony/var-dumper": "^6.3|^7.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Pail\\PailServiceProvider" + ] + }, + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Pail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Easily delve into your Laravel application's log files directly from the command line.", + "homepage": "https://github.com/laravel/pail", + "keywords": [ + "laravel", + "logs", + "php", + "tail" + ], + "support": { + "issues": "https://github.com/laravel/pail/issues", + "source": "https://github.com/laravel/pail" + }, + "time": "2025-01-28T15:15:15+00:00" + }, + { + "name": "laravel/pint", + "version": "v1.22.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/pint.git", + "reference": "7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pint/zipball/7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36", + "reference": "7ddfaa6523a675fae5c4123ee38fc6bfb8ee4f36", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-mbstring": "*", + "ext-tokenizer": "*", + "ext-xml": "*", + "php": "^8.2.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.75.0", + "illuminate/view": "^11.44.2", + "larastan/larastan": "^3.3.1", + "laravel-zero/framework": "^11.36.1", + "mockery/mockery": "^1.6.12", + "nunomaduro/termwind": "^2.3", + "pestphp/pest": "^2.36.0" + }, + "bin": [ + "builds/pint" + ], + "type": "project", + "autoload": { + "psr-4": { + "App\\": "app/", + "Database\\Seeders\\": "database/seeders/", + "Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "An opinionated code formatter for PHP.", + "homepage": "https://laravel.com", + "keywords": [ + "format", + "formatter", + "lint", + "linter", + "php" + ], + "support": { + "issues": "https://github.com/laravel/pint/issues", + "source": "https://github.com/laravel/pint" + }, + "time": "2025-04-08T22:11:45+00:00" + }, + { + "name": "laravel/sail", + "version": "v1.42.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/sail.git", + "reference": "2edaaf77f3c07a4099965bb3d7dfee16e801c0f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sail/zipball/2edaaf77f3c07a4099965bb3d7dfee16e801c0f6", + "reference": "2edaaf77f3c07a4099965bb3d7dfee16e801c0f6", + "shasum": "" + }, + "require": { + "illuminate/console": "^9.52.16|^10.0|^11.0|^12.0", + "illuminate/contracts": "^9.52.16|^10.0|^11.0|^12.0", + "illuminate/support": "^9.52.16|^10.0|^11.0|^12.0", + "php": "^8.0", + "symfony/console": "^6.0|^7.0", + "symfony/yaml": "^6.0|^7.0" + }, + "require-dev": { + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", + "phpstan/phpstan": "^1.10" + }, + "bin": [ + "bin/sail" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Sail\\SailServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Docker files for running a basic Laravel application.", + "keywords": [ + "docker", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/sail/issues", + "source": "https://github.com/laravel/sail" + }, + "time": "2025-04-29T14:26:46+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Pádraic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.13.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2025-04-29T12:36:36+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v8.8.0", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/4cf9f3b47afff38b139fb79ce54fc71799022ce8", + "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.18.0", + "nunomaduro/termwind": "^2.3.0", + "php": "^8.2.0", + "symfony/console": "^7.2.5" + }, + "conflict": { + "laravel/framework": "<11.44.2 || >=13.0.0", + "phpunit/phpunit": "<11.5.15 || >=13.0.0" + }, + "require-dev": { + "brianium/paratest": "^7.8.3", + "larastan/larastan": "^3.2", + "laravel/framework": "^11.44.2 || ^12.6", + "laravel/pint": "^1.21.2", + "laravel/sail": "^1.41.0", + "laravel/sanctum": "^4.0.8", + "laravel/tinker": "^2.10.1", + "orchestra/testbench-core": "^9.12.0 || ^10.1", + "pestphp/pest": "^3.8.0", + "sebastian/environment": "^7.2.0 || ^8.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + }, + "branch-alias": { + "dev-8.x": "8.x-dev" + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "dev", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2025-04-03T14:33:09+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "11.0.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/14d63fbcca18457e49c6f8bebaa91a87e8e188d7", + "reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.4.0", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.0", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^11.5.2" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.9" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-02-25T13:26:39+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-27T05:02:59+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:07:44+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:08:43+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:09:35+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "11.5.18", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "fc3e887c7f3f9917e1bf61e523413d753db00a17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc3e887c7f3f9917e1bf61e523413d753db00a17", + "reference": "fc3e887c7f3f9917e1bf61e523413d753db00a17", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.13.0", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.9", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.3", + "sebastian/comparator": "^6.3.1", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.0", + "sebastian/exporter": "^6.3.0", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.2", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.18" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2025-04-22T06:09:49+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:41:36+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-19T07:56:08+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:45:54+00:00" + }, + { + "name": "sebastian/comparator", + "version": "6.3.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/24b8fbc2c8e201bb1308e7b05148d6ab393b6959", + "reference": "24b8fbc2c8e201bb1308e7b05148d6ab393b6959", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.4" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.3-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-07T06:57:01+00:00" + }, + { + "name": "sebastian/complexity", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:49:50+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:53:05+00:00" + }, + { + "name": "sebastian/environment", + "version": "7.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:54:44+00:00" + }, + { + "name": "sebastian/exporter", + "version": "6.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-12-05T09:17:50+00:00" + }, + { + "name": "sebastian/global-state", + "version": "7.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:57:36+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:58:38+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:00:13+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:01:32+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:10:34+00:00" + }, + { + "name": "sebastian/type", + "version": "5.1.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", + "reference": "a8a7e30534b0eb0c77cd9d07e82de1a114389f5e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-03-18T13:35:50+00:00" + }, + { + "name": "sebastian/version", + "version": "5.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-10-09T05:16:32+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { + "name": "symfony/yaml", + "version": "v7.2.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "4c4b6f4cfcd7e52053f0c8bfad0f7f30fb924912" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/4c4b6f4cfcd7e52053f0c8bfad0f7f30fb924912", + "reference": "4c4b6f4cfcd7e52053f0c8bfad0f7f30fb924912", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "symfony/console": "^6.4|^7.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v7.2.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-03-03T07:12:39+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": true, + "prefer-lowest": false, + "platform": { + "php": "^8.2" + }, + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/config/app.php b/config/app.php new file mode 100644 index 0000000..f467267 --- /dev/null +++ b/config/app.php @@ -0,0 +1,126 @@ + env('APP_NAME', 'Laravel'), + + /* + |-------------------------------------------------------------------------- + | Application Environment + |-------------------------------------------------------------------------- + | + | This value determines the "environment" your application is currently + | running in. This may determine how you prefer to configure various + | services the application utilizes. Set this in your ".env" file. + | + */ + + 'env' => env('APP_ENV', 'production'), + + /* + |-------------------------------------------------------------------------- + | Application Debug Mode + |-------------------------------------------------------------------------- + | + | When your application is in debug mode, detailed error messages with + | stack traces will be shown on every error that occurs within your + | application. If disabled, a simple generic error page is shown. + | + */ + + 'debug' => (bool) env('APP_DEBUG', false), + + /* + |-------------------------------------------------------------------------- + | Application URL + |-------------------------------------------------------------------------- + | + | This URL is used by the console to properly generate URLs when using + | the Artisan command line tool. You should set this to the root of + | the application so that it's available within Artisan commands. + | + */ + + 'url' => env('APP_URL', 'http://localhost'), + + /* + |-------------------------------------------------------------------------- + | Application Timezone + |-------------------------------------------------------------------------- + | + | Here you may specify the default timezone for your application, which + | will be used by the PHP date and date-time functions. The timezone + | is set to "UTC" by default as it is suitable for most use cases. + | + */ + + 'timezone' => env('APP_TIMEZONE', 'UTC'), + + /* + |-------------------------------------------------------------------------- + | Application Locale Configuration + |-------------------------------------------------------------------------- + | + | The application locale determines the default locale that will be used + | by Laravel's translation / localization methods. This option can be + | set to any locale for which you plan to have translation strings. + | + */ + + 'locale' => env('APP_LOCALE', 'en'), + + 'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'), + + 'faker_locale' => env('APP_FAKER_LOCALE', 'en_US'), + + /* + |-------------------------------------------------------------------------- + | Encryption Key + |-------------------------------------------------------------------------- + | + | This key is utilized by Laravel's encryption services and should be set + | to a random, 32 character string to ensure that all encrypted values + | are secure. You should do this prior to deploying the application. + | + */ + + 'cipher' => 'AES-256-CBC', + + 'key' => env('APP_KEY'), + + 'previous_keys' => [ + ...array_filter( + explode(',', env('APP_PREVIOUS_KEYS', '')) + ), + ], + + /* + |-------------------------------------------------------------------------- + | Maintenance Mode Driver + |-------------------------------------------------------------------------- + | + | These configuration options determine the driver used to determine and + | manage Laravel's "maintenance mode" status. The "cache" driver will + | allow maintenance mode to be controlled across multiple machines. + | + | Supported drivers: "file", "cache" + | + */ + + 'maintenance' => [ + 'driver' => env('APP_MAINTENANCE_DRIVER', 'file'), + 'store' => env('APP_MAINTENANCE_STORE', 'database'), + ], + +]; diff --git a/config/auth.php b/config/auth.php new file mode 100644 index 0000000..0ba5d5d --- /dev/null +++ b/config/auth.php @@ -0,0 +1,115 @@ + [ + 'guard' => env('AUTH_GUARD', 'web'), + 'passwords' => env('AUTH_PASSWORD_BROKER', 'users'), + ], + + /* + |-------------------------------------------------------------------------- + | Authentication Guards + |-------------------------------------------------------------------------- + | + | Next, you may define every authentication guard for your application. + | Of course, a great default configuration has been defined for you + | which utilizes session storage plus the Eloquent user provider. + | + | All authentication guards have a user provider, which defines how the + | users are actually retrieved out of your database or other storage + | system used by the application. Typically, Eloquent is utilized. + | + | Supported: "session" + | + */ + + 'guards' => [ + 'web' => [ + 'driver' => 'session', + 'provider' => 'users', + ], + ], + + /* + |-------------------------------------------------------------------------- + | User Providers + |-------------------------------------------------------------------------- + | + | All authentication guards have a user provider, which defines how the + | users are actually retrieved out of your database or other storage + | system used by the application. Typically, Eloquent is utilized. + | + | If you have multiple user tables or models you may configure multiple + | providers to represent the model / table. These providers may then + | be assigned to any extra authentication guards you have defined. + | + | Supported: "database", "eloquent" + | + */ + + 'providers' => [ + 'users' => [ + 'driver' => 'eloquent', + 'model' => env('AUTH_MODEL', App\Models\User::class), + ], + + // 'users' => [ + // 'driver' => 'database', + // 'table' => 'users', + // ], + ], + + /* + |-------------------------------------------------------------------------- + | Resetting Passwords + |-------------------------------------------------------------------------- + | + | These configuration options specify the behavior of Laravel's password + | reset functionality, including the table utilized for token storage + | and the user provider that is invoked to actually retrieve users. + | + | The expiry time is the number of minutes that each reset token will be + | considered valid. This security feature keeps tokens short-lived so + | they have less time to be guessed. You may change this as needed. + | + | The throttle setting is the number of seconds a user must wait before + | generating more password reset tokens. This prevents the user from + | quickly generating a very large amount of password reset tokens. + | + */ + + 'passwords' => [ + 'users' => [ + 'provider' => 'users', + 'table' => env('AUTH_PASSWORD_RESET_TOKEN_TABLE', 'password_reset_tokens'), + 'expire' => 60, + 'throttle' => 60, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Password Confirmation Timeout + |-------------------------------------------------------------------------- + | + | Here you may define the amount of seconds before a password confirmation + | window expires and users are asked to re-enter their password via the + | confirmation screen. By default, the timeout lasts for three hours. + | + */ + + 'password_timeout' => env('AUTH_PASSWORD_TIMEOUT', 10800), + +]; diff --git a/config/cache.php b/config/cache.php new file mode 100644 index 0000000..925f7d2 --- /dev/null +++ b/config/cache.php @@ -0,0 +1,108 @@ + env('CACHE_STORE', 'database'), + + /* + |-------------------------------------------------------------------------- + | Cache Stores + |-------------------------------------------------------------------------- + | + | Here you may define all of the cache "stores" for your application as + | well as their drivers. You may even define multiple stores for the + | same cache driver to group types of items stored in your caches. + | + | Supported drivers: "array", "database", "file", "memcached", + | "redis", "dynamodb", "octane", "null" + | + */ + + 'stores' => [ + + 'array' => [ + 'driver' => 'array', + 'serialize' => false, + ], + + 'database' => [ + 'driver' => 'database', + 'connection' => env('DB_CACHE_CONNECTION'), + 'table' => env('DB_CACHE_TABLE', 'cache'), + 'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'), + 'lock_table' => env('DB_CACHE_LOCK_TABLE'), + ], + + 'file' => [ + 'driver' => 'file', + 'path' => storage_path('framework/cache/data'), + 'lock_path' => storage_path('framework/cache/data'), + ], + + 'memcached' => [ + 'driver' => 'memcached', + 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), + 'sasl' => [ + env('MEMCACHED_USERNAME'), + env('MEMCACHED_PASSWORD'), + ], + 'options' => [ + // Memcached::OPT_CONNECT_TIMEOUT => 2000, + ], + 'servers' => [ + [ + 'host' => env('MEMCACHED_HOST', '127.0.0.1'), + 'port' => env('MEMCACHED_PORT', 11211), + 'weight' => 100, + ], + ], + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => env('REDIS_CACHE_CONNECTION', 'cache'), + 'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'), + ], + + 'dynamodb' => [ + 'driver' => 'dynamodb', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), + 'endpoint' => env('DYNAMODB_ENDPOINT'), + ], + + 'octane' => [ + 'driver' => 'octane', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Cache Key Prefix + |-------------------------------------------------------------------------- + | + | When utilizing the APC, database, memcached, Redis, and DynamoDB cache + | stores, there might be other applications using the same cache. For + | that reason, you may prefix every cache key to avoid collisions. + | + */ + + 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'), + +]; diff --git a/config/database.php b/config/database.php new file mode 100644 index 0000000..125949e --- /dev/null +++ b/config/database.php @@ -0,0 +1,173 @@ + env('DB_CONNECTION', 'sqlite'), + + /* + |-------------------------------------------------------------------------- + | Database Connections + |-------------------------------------------------------------------------- + | + | Below are all of the database connections defined for your application. + | An example configuration is provided for each database system which + | is supported by Laravel. You're free to add / remove connections. + | + */ + + 'connections' => [ + + 'sqlite' => [ + 'driver' => 'sqlite', + 'url' => env('DB_URL'), + 'database' => env('DB_DATABASE', database_path('database.sqlite')), + 'prefix' => '', + 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), + 'busy_timeout' => null, + 'journal_mode' => null, + 'synchronous' => null, + ], + + 'mysql' => [ + 'driver' => 'mysql', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'laravel'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => env('DB_CHARSET', 'utf8mb4'), + 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'), + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => true, + 'engine' => null, + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + + 'mariadb' => [ + 'driver' => 'mariadb', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '3306'), + 'database' => env('DB_DATABASE', 'laravel'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'unix_socket' => env('DB_SOCKET', ''), + 'charset' => env('DB_CHARSET', 'utf8mb4'), + 'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'), + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => true, + 'engine' => null, + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + ], + + 'pgsql' => [ + 'driver' => 'pgsql', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', '127.0.0.1'), + 'port' => env('DB_PORT', '5432'), + 'database' => env('DB_DATABASE', 'laravel'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => env('DB_CHARSET', 'utf8'), + 'prefix' => '', + 'prefix_indexes' => true, + 'search_path' => 'public', + 'sslmode' => 'prefer', + ], + + 'sqlsrv' => [ + 'driver' => 'sqlsrv', + 'url' => env('DB_URL'), + 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', '1433'), + 'database' => env('DB_DATABASE', 'laravel'), + 'username' => env('DB_USERNAME', 'root'), + 'password' => env('DB_PASSWORD', ''), + 'charset' => env('DB_CHARSET', 'utf8'), + 'prefix' => '', + 'prefix_indexes' => true, + // 'encrypt' => env('DB_ENCRYPT', 'yes'), + // 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'), + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run on the database. + | + */ + + 'migrations' => [ + 'table' => 'migrations', + 'update_date_on_publish' => true, + ], + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer body of commands than a typical key-value system + | such as Memcached. You may define your connection settings here. + | + */ + + 'redis' => [ + + 'client' => env('REDIS_CLIENT', 'phpredis'), + + 'options' => [ + 'cluster' => env('REDIS_CLUSTER', 'redis'), + 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), + ], + + 'default' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_DB', '0'), + ], + + 'cache' => [ + 'url' => env('REDIS_URL'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'username' => env('REDIS_USERNAME'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'database' => env('REDIS_CACHE_DB', '1'), + ], + + ], + +]; diff --git a/config/excel.php b/config/excel.php new file mode 100644 index 0000000..c1fd34a --- /dev/null +++ b/config/excel.php @@ -0,0 +1,380 @@ + [ + + /* + |-------------------------------------------------------------------------- + | Chunk size + |-------------------------------------------------------------------------- + | + | When using FromQuery, the query is automatically chunked. + | Here you can specify how big the chunk should be. + | + */ + 'chunk_size' => 1000, + + /* + |-------------------------------------------------------------------------- + | Pre-calculate formulas during export + |-------------------------------------------------------------------------- + */ + 'pre_calculate_formulas' => false, + + /* + |-------------------------------------------------------------------------- + | Enable strict null comparison + |-------------------------------------------------------------------------- + | + | When enabling strict null comparison empty cells ('') will + | be added to the sheet. + */ + 'strict_null_comparison' => false, + + /* + |-------------------------------------------------------------------------- + | CSV Settings + |-------------------------------------------------------------------------- + | + | Configure e.g. delimiter, enclosure and line ending for CSV exports. + | + */ + 'csv' => [ + 'delimiter' => ',', + 'enclosure' => '"', + 'line_ending' => PHP_EOL, + 'use_bom' => false, + 'include_separator_line' => false, + 'excel_compatibility' => false, + 'output_encoding' => '', + 'test_auto_detect' => true, + ], + + /* + |-------------------------------------------------------------------------- + | Worksheet properties + |-------------------------------------------------------------------------- + | + | Configure e.g. default title, creator, subject,... + | + */ + 'properties' => [ + 'creator' => '', + 'lastModifiedBy' => '', + 'title' => '', + 'description' => '', + 'subject' => '', + 'keywords' => '', + 'category' => '', + 'manager' => '', + 'company' => '', + ], + ], + + 'imports' => [ + + /* + |-------------------------------------------------------------------------- + | Read Only + |-------------------------------------------------------------------------- + | + | When dealing with imports, you might only be interested in the + | data that the sheet exists. By default we ignore all styles, + | however if you want to do some logic based on style data + | you can enable it by setting read_only to false. + | + */ + 'read_only' => true, + + /* + |-------------------------------------------------------------------------- + | Ignore Empty + |-------------------------------------------------------------------------- + | + | When dealing with imports, you might be interested in ignoring + | rows that have null values or empty strings. By default rows + | containing empty strings or empty values are not ignored but can be + | ignored by enabling the setting ignore_empty to true. + | + */ + 'ignore_empty' => false, + + /* + |-------------------------------------------------------------------------- + | Heading Row Formatter + |-------------------------------------------------------------------------- + | + | Configure the heading row formatter. + | Available options: none|slug|custom + | + */ + 'heading_row' => [ + 'formatter' => 'slug', + ], + + /* + |-------------------------------------------------------------------------- + | CSV Settings + |-------------------------------------------------------------------------- + | + | Configure e.g. delimiter, enclosure and line ending for CSV imports. + | + */ + 'csv' => [ + 'delimiter' => null, + 'enclosure' => '"', + 'escape_character' => '\\', + 'contiguous' => false, + 'input_encoding' => Csv::GUESS_ENCODING, + ], + + /* + |-------------------------------------------------------------------------- + | Worksheet properties + |-------------------------------------------------------------------------- + | + | Configure e.g. default title, creator, subject,... + | + */ + 'properties' => [ + 'creator' => '', + 'lastModifiedBy' => '', + 'title' => '', + 'description' => '', + 'subject' => '', + 'keywords' => '', + 'category' => '', + 'manager' => '', + 'company' => '', + ], + + /* + |-------------------------------------------------------------------------- + | Cell Middleware + |-------------------------------------------------------------------------- + | + | Configure middleware that is executed on getting a cell value + | + */ + 'cells' => [ + 'middleware' => [ + //\Maatwebsite\Excel\Middleware\TrimCellValue::class, + //\Maatwebsite\Excel\Middleware\ConvertEmptyCellValuesToNull::class, + ], + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Extension detector + |-------------------------------------------------------------------------- + | + | Configure here which writer/reader type should be used when the package + | needs to guess the correct type based on the extension alone. + | + */ + 'extension_detector' => [ + 'xlsx' => Excel::XLSX, + 'xlsm' => Excel::XLSX, + 'xltx' => Excel::XLSX, + 'xltm' => Excel::XLSX, + 'xls' => Excel::XLS, + 'xlt' => Excel::XLS, + 'ods' => Excel::ODS, + 'ots' => Excel::ODS, + 'slk' => Excel::SLK, + 'xml' => Excel::XML, + 'gnumeric' => Excel::GNUMERIC, + 'htm' => Excel::HTML, + 'html' => Excel::HTML, + 'csv' => Excel::CSV, + 'tsv' => Excel::TSV, + + /* + |-------------------------------------------------------------------------- + | PDF Extension + |-------------------------------------------------------------------------- + | + | Configure here which Pdf driver should be used by default. + | Available options: Excel::MPDF | Excel::TCPDF | Excel::DOMPDF + | + */ + 'pdf' => Excel::DOMPDF, + ], + + /* + |-------------------------------------------------------------------------- + | Value Binder + |-------------------------------------------------------------------------- + | + | PhpSpreadsheet offers a way to hook into the process of a value being + | written to a cell. In there some assumptions are made on how the + | value should be formatted. If you want to change those defaults, + | you can implement your own default value binder. + | + | Possible value binders: + | + | [x] Maatwebsite\Excel\DefaultValueBinder::class + | [x] PhpOffice\PhpSpreadsheet\Cell\StringValueBinder::class + | [x] PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder::class + | + */ + 'value_binder' => [ + 'default' => Maatwebsite\Excel\DefaultValueBinder::class, + ], + + 'cache' => [ + /* + |-------------------------------------------------------------------------- + | Default cell caching driver + |-------------------------------------------------------------------------- + | + | By default PhpSpreadsheet keeps all cell values in memory, however when + | dealing with large files, this might result into memory issues. If you + | want to mitigate that, you can configure a cell caching driver here. + | When using the illuminate driver, it will store each value in the + | cache store. This can slow down the process, because it needs to + | store each value. You can use the "batch" store if you want to + | only persist to the store when the memory limit is reached. + | + | Drivers: memory|illuminate|batch + | + */ + 'driver' => 'memory', + + /* + |-------------------------------------------------------------------------- + | Batch memory caching + |-------------------------------------------------------------------------- + | + | When dealing with the "batch" caching driver, it will only + | persist to the store when the memory limit is reached. + | Here you can tweak the memory limit to your liking. + | + */ + 'batch' => [ + 'memory_limit' => 60000, + ], + + /* + |-------------------------------------------------------------------------- + | Illuminate cache + |-------------------------------------------------------------------------- + | + | When using the "illuminate" caching driver, it will automatically use + | your default cache store. However if you prefer to have the cell + | cache on a separate store, you can configure the store name here. + | You can use any store defined in your cache config. When leaving + | at "null" it will use the default store. + | + */ + 'illuminate' => [ + 'store' => null, + ], + + /* + |-------------------------------------------------------------------------- + | Cache Time-to-live (TTL) + |-------------------------------------------------------------------------- + | + | The TTL of items written to cache. If you want to keep the items cached + | indefinitely, set this to null. Otherwise, set a number of seconds, + | a \DateInterval, or a callable. + | + | Allowable types: callable|\DateInterval|int|null + | + */ + 'default_ttl' => 10800, + ], + + /* + |-------------------------------------------------------------------------- + | Transaction Handler + |-------------------------------------------------------------------------- + | + | By default the import is wrapped in a transaction. This is useful + | for when an import may fail and you want to retry it. With the + | transactions, the previous import gets rolled-back. + | + | You can disable the transaction handler by setting this to null. + | Or you can choose a custom made transaction handler here. + | + | Supported handlers: null|db + | + */ + 'transactions' => [ + 'handler' => 'db', + 'db' => [ + 'connection' => null, + ], + ], + + 'temporary_files' => [ + + /* + |-------------------------------------------------------------------------- + | Local Temporary Path + |-------------------------------------------------------------------------- + | + | When exporting and importing files, we use a temporary file, before + | storing reading or downloading. Here you can customize that path. + | permissions is an array with the permission flags for the directory (dir) + | and the create file (file). + | + */ + 'local_path' => storage_path('framework/cache/laravel-excel'), + + /* + |-------------------------------------------------------------------------- + | Local Temporary Path Permissions + |-------------------------------------------------------------------------- + | + | Permissions is an array with the permission flags for the directory (dir) + | and the create file (file). + | If omitted the default permissions of the filesystem will be used. + | + */ + 'local_permissions' => [ + // 'dir' => 0755, + // 'file' => 0644, + ], + + /* + |-------------------------------------------------------------------------- + | Remote Temporary Disk + |-------------------------------------------------------------------------- + | + | When dealing with a multi server setup with queues in which you + | cannot rely on having a shared local temporary path, you might + | want to store the temporary file on a shared disk. During the + | queue executing, we'll retrieve the temporary file from that + | location instead. When left to null, it will always use + | the local path. This setting only has effect when using + | in conjunction with queued imports and exports. + | + */ + 'remote_disk' => null, + 'remote_prefix' => null, + + /* + |-------------------------------------------------------------------------- + | Force Resync + |-------------------------------------------------------------------------- + | + | When dealing with a multi server setup as above, it's possible + | for the clean up that occurs after entire queue has been run to only + | cleanup the server that the last AfterImportJob runs on. The rest of the server + | would still have the local temporary file stored on it. In this case your + | local storage limits can be exceeded and future imports won't be processed. + | To mitigate this you can set this config value to be true, so that after every + | queued chunk is processed the local temporary file is deleted on the server that + | processed it. + | + */ + 'force_resync_remote' => null, + ], +]; diff --git a/config/filesystems.php b/config/filesystems.php new file mode 100644 index 0000000..3d671bd --- /dev/null +++ b/config/filesystems.php @@ -0,0 +1,80 @@ + env('FILESYSTEM_DISK', 'local'), + + /* + |-------------------------------------------------------------------------- + | Filesystem Disks + |-------------------------------------------------------------------------- + | + | Below you may configure as many filesystem disks as necessary, and you + | may even configure multiple disks for the same driver. Examples for + | most supported storage drivers are configured here for reference. + | + | Supported drivers: "local", "ftp", "sftp", "s3" + | + */ + + 'disks' => [ + + 'local' => [ + 'driver' => 'local', + 'root' => storage_path('app/private'), + 'serve' => true, + 'throw' => false, + 'report' => false, + ], + + 'public' => [ + 'driver' => 'local', + 'root' => storage_path('app/public'), + 'url' => env('APP_URL').'/storage', + 'visibility' => 'public', + 'throw' => false, + 'report' => false, + ], + + 's3' => [ + 'driver' => 's3', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION'), + 'bucket' => env('AWS_BUCKET'), + 'url' => env('AWS_URL'), + 'endpoint' => env('AWS_ENDPOINT'), + 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), + 'throw' => false, + 'report' => false, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Symbolic Links + |-------------------------------------------------------------------------- + | + | Here you may configure the symbolic links that will be created when the + | `storage:link` Artisan command is executed. The array keys should be + | the locations of the links and the values should be their targets. + | + */ + + 'links' => [ + public_path('storage') => storage_path('app/public'), + ], + +]; diff --git a/config/logging.php b/config/logging.php new file mode 100644 index 0000000..8d94292 --- /dev/null +++ b/config/logging.php @@ -0,0 +1,132 @@ + env('LOG_CHANNEL', 'stack'), + + /* + |-------------------------------------------------------------------------- + | Deprecations Log Channel + |-------------------------------------------------------------------------- + | + | This option controls the log channel that should be used to log warnings + | regarding deprecated PHP and library features. This allows you to get + | your application ready for upcoming major versions of dependencies. + | + */ + + 'deprecations' => [ + 'channel' => env('LOG_DEPRECATIONS_CHANNEL', 'null'), + 'trace' => env('LOG_DEPRECATIONS_TRACE', false), + ], + + /* + |-------------------------------------------------------------------------- + | Log Channels + |-------------------------------------------------------------------------- + | + | Here you may configure the log channels for your application. Laravel + | utilizes the Monolog PHP logging library, which includes a variety + | of powerful log handlers and formatters that you're free to use. + | + | Available drivers: "single", "daily", "slack", "syslog", + | "errorlog", "monolog", "custom", "stack" + | + */ + + 'channels' => [ + + 'stack' => [ + 'driver' => 'stack', + 'channels' => explode(',', env('LOG_STACK', 'single')), + 'ignore_exceptions' => false, + ], + + 'single' => [ + 'driver' => 'single', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'replace_placeholders' => true, + ], + + 'daily' => [ + 'driver' => 'daily', + 'path' => storage_path('logs/laravel.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'days' => env('LOG_DAILY_DAYS', 14), + 'replace_placeholders' => true, + ], + + 'slack' => [ + 'driver' => 'slack', + 'url' => env('LOG_SLACK_WEBHOOK_URL'), + 'username' => env('LOG_SLACK_USERNAME', 'Laravel Log'), + 'emoji' => env('LOG_SLACK_EMOJI', ':boom:'), + 'level' => env('LOG_LEVEL', 'critical'), + 'replace_placeholders' => true, + ], + + 'papertrail' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class), + 'handler_with' => [ + 'host' => env('PAPERTRAIL_URL'), + 'port' => env('PAPERTRAIL_PORT'), + 'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'), + ], + 'processors' => [PsrLogMessageProcessor::class], + ], + + 'stderr' => [ + 'driver' => 'monolog', + 'level' => env('LOG_LEVEL', 'debug'), + 'handler' => StreamHandler::class, + 'formatter' => env('LOG_STDERR_FORMATTER'), + 'with' => [ + 'stream' => 'php://stderr', + ], + 'processors' => [PsrLogMessageProcessor::class], + ], + + 'syslog' => [ + 'driver' => 'syslog', + 'level' => env('LOG_LEVEL', 'debug'), + 'facility' => env('LOG_SYSLOG_FACILITY', LOG_USER), + 'replace_placeholders' => true, + ], + + 'errorlog' => [ + 'driver' => 'errorlog', + 'level' => env('LOG_LEVEL', 'debug'), + 'replace_placeholders' => true, + ], + + 'null' => [ + 'driver' => 'monolog', + 'handler' => NullHandler::class, + ], + + 'emergency' => [ + 'path' => storage_path('logs/laravel.log'), + ], + + ], + +]; diff --git a/config/mail.php b/config/mail.php new file mode 100644 index 0000000..756305b --- /dev/null +++ b/config/mail.php @@ -0,0 +1,116 @@ + env('MAIL_MAILER', 'log'), + + /* + |-------------------------------------------------------------------------- + | Mailer Configurations + |-------------------------------------------------------------------------- + | + | Here you may configure all of the mailers used by your application plus + | their respective settings. Several examples have been configured for + | you and you are free to add your own as your application requires. + | + | Laravel supports a variety of mail "transport" drivers that can be used + | when delivering an email. You may specify which one you're using for + | your mailers below. You may also add additional mailers if needed. + | + | Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2", + | "postmark", "resend", "log", "array", + | "failover", "roundrobin" + | + */ + + 'mailers' => [ + + 'smtp' => [ + 'transport' => 'smtp', + 'scheme' => env('MAIL_SCHEME'), + 'url' => env('MAIL_URL'), + 'host' => env('MAIL_HOST', '127.0.0.1'), + 'port' => env('MAIL_PORT', 2525), + 'username' => env('MAIL_USERNAME'), + 'password' => env('MAIL_PASSWORD'), + 'timeout' => null, + 'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)), + ], + + 'ses' => [ + 'transport' => 'ses', + ], + + 'postmark' => [ + 'transport' => 'postmark', + // 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'), + // 'client' => [ + // 'timeout' => 5, + // ], + ], + + 'resend' => [ + 'transport' => 'resend', + ], + + 'sendmail' => [ + 'transport' => 'sendmail', + 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'), + ], + + 'log' => [ + 'transport' => 'log', + 'channel' => env('MAIL_LOG_CHANNEL'), + ], + + 'array' => [ + 'transport' => 'array', + ], + + 'failover' => [ + 'transport' => 'failover', + 'mailers' => [ + 'smtp', + 'log', + ], + ], + + 'roundrobin' => [ + 'transport' => 'roundrobin', + 'mailers' => [ + 'ses', + 'postmark', + ], + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Global "From" Address + |-------------------------------------------------------------------------- + | + | You may wish for all emails sent by your application to be sent from + | the same address. Here you may specify a name and address that is + | used globally for all emails that are sent by your application. + | + */ + + 'from' => [ + 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), + 'name' => env('MAIL_FROM_NAME', 'Example'), + ], + +]; diff --git a/config/queue.php b/config/queue.php new file mode 100644 index 0000000..116bd8d --- /dev/null +++ b/config/queue.php @@ -0,0 +1,112 @@ + env('QUEUE_CONNECTION', 'database'), + + /* + |-------------------------------------------------------------------------- + | Queue Connections + |-------------------------------------------------------------------------- + | + | Here you may configure the connection options for every queue backend + | used by your application. An example configuration is provided for + | each backend supported by Laravel. You're also free to add more. + | + | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" + | + */ + + 'connections' => [ + + 'sync' => [ + 'driver' => 'sync', + ], + + 'database' => [ + 'driver' => 'database', + 'connection' => env('DB_QUEUE_CONNECTION'), + 'table' => env('DB_QUEUE_TABLE', 'jobs'), + 'queue' => env('DB_QUEUE', 'default'), + 'retry_after' => (int) env('DB_QUEUE_RETRY_AFTER', 90), + 'after_commit' => false, + ], + + 'beanstalkd' => [ + 'driver' => 'beanstalkd', + 'host' => env('BEANSTALKD_QUEUE_HOST', 'localhost'), + 'queue' => env('BEANSTALKD_QUEUE', 'default'), + 'retry_after' => (int) env('BEANSTALKD_QUEUE_RETRY_AFTER', 90), + 'block_for' => 0, + 'after_commit' => false, + ], + + 'sqs' => [ + 'driver' => 'sqs', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), + 'queue' => env('SQS_QUEUE', 'default'), + 'suffix' => env('SQS_SUFFIX'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'after_commit' => false, + ], + + 'redis' => [ + 'driver' => 'redis', + 'connection' => env('REDIS_QUEUE_CONNECTION', 'default'), + 'queue' => env('REDIS_QUEUE', 'default'), + 'retry_after' => (int) env('REDIS_QUEUE_RETRY_AFTER', 90), + 'block_for' => null, + 'after_commit' => false, + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Job Batching + |-------------------------------------------------------------------------- + | + | The following options configure the database and table that store job + | batching information. These options can be updated to any database + | connection and table which has been defined by your application. + | + */ + + 'batching' => [ + 'database' => env('DB_CONNECTION', 'sqlite'), + 'table' => 'job_batches', + ], + + /* + |-------------------------------------------------------------------------- + | Failed Queue Jobs + |-------------------------------------------------------------------------- + | + | These options configure the behavior of failed queue job logging so you + | can control how and where failed jobs are stored. Laravel ships with + | support for storing failed jobs in a simple file or in a database. + | + | Supported drivers: "database-uuids", "dynamodb", "file", "null" + | + */ + + 'failed' => [ + 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), + 'database' => env('DB_CONNECTION', 'sqlite'), + 'table' => 'failed_jobs', + ], + +]; diff --git a/config/sanctum.php b/config/sanctum.php new file mode 100644 index 0000000..764a82f --- /dev/null +++ b/config/sanctum.php @@ -0,0 +1,83 @@ + explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( + '%s%s', + 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', + Sanctum::currentApplicationUrlWithPort() + ))), + + /* + |-------------------------------------------------------------------------- + | Sanctum Guards + |-------------------------------------------------------------------------- + | + | This array contains the authentication guards that will be checked when + | Sanctum is trying to authenticate a request. If none of these guards + | are able to authenticate the request, Sanctum will use the bearer + | token that's present on an incoming request for authentication. + | + */ + + 'guard' => ['web'], + + /* + |-------------------------------------------------------------------------- + | Expiration Minutes + |-------------------------------------------------------------------------- + | + | This value controls the number of minutes until an issued token will be + | considered expired. This will override any values set in the token's + | "expires_at" attribute, but first-party sessions are not affected. + | + */ + + 'expiration' => null, + + /* + |-------------------------------------------------------------------------- + | Token Prefix + |-------------------------------------------------------------------------- + | + | Sanctum can prefix new tokens in order to take advantage of numerous + | security scanning initiatives maintained by open source platforms + | that notify developers if they commit tokens into repositories. + | + | See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning + | + */ + + 'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''), + + /* + |-------------------------------------------------------------------------- + | Sanctum Middleware + |-------------------------------------------------------------------------- + | + | When authenticating your first-party SPA with Sanctum you may need to + | customize some of the middleware Sanctum uses while processing the + | request. You may change the middleware listed below as required. + | + */ + + 'middleware' => [ + 'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class, + 'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class, + 'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class, + ], + +]; diff --git a/config/services.php b/config/services.php new file mode 100644 index 0000000..27a3617 --- /dev/null +++ b/config/services.php @@ -0,0 +1,38 @@ + [ + 'token' => env('POSTMARK_TOKEN'), + ], + + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + ], + + 'resend' => [ + 'key' => env('RESEND_KEY'), + ], + + 'slack' => [ + 'notifications' => [ + 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), + 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), + ], + ], + +]; diff --git a/config/session.php b/config/session.php new file mode 100644 index 0000000..ba0aa60 --- /dev/null +++ b/config/session.php @@ -0,0 +1,217 @@ + env('SESSION_DRIVER', 'database'), + + /* + |-------------------------------------------------------------------------- + | Session Lifetime + |-------------------------------------------------------------------------- + | + | Here you may specify the number of minutes that you wish the session + | to be allowed to remain idle before it expires. If you want them + | to expire immediately when the browser is closed then you may + | indicate that via the expire_on_close configuration option. + | + */ + + 'lifetime' => (int) env('SESSION_LIFETIME', 120), + + 'expire_on_close' => env('SESSION_EXPIRE_ON_CLOSE', false), + + /* + |-------------------------------------------------------------------------- + | Session Encryption + |-------------------------------------------------------------------------- + | + | This option allows you to easily specify that all of your session data + | should be encrypted before it's stored. All encryption is performed + | automatically by Laravel and you may use the session like normal. + | + */ + + 'encrypt' => env('SESSION_ENCRYPT', false), + + /* + |-------------------------------------------------------------------------- + | Session File Location + |-------------------------------------------------------------------------- + | + | When utilizing the "file" session driver, the session files are placed + | on disk. The default storage location is defined here; however, you + | are free to provide another location where they should be stored. + | + */ + + 'files' => storage_path('framework/sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Database Connection + |-------------------------------------------------------------------------- + | + | When using the "database" or "redis" session drivers, you may specify a + | connection that should be used to manage these sessions. This should + | correspond to a connection in your database configuration options. + | + */ + + 'connection' => env('SESSION_CONNECTION'), + + /* + |-------------------------------------------------------------------------- + | Session Database Table + |-------------------------------------------------------------------------- + | + | When using the "database" session driver, you may specify the table to + | be used to store sessions. Of course, a sensible default is defined + | for you; however, you're welcome to change this to another table. + | + */ + + 'table' => env('SESSION_TABLE', 'sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Cache Store + |-------------------------------------------------------------------------- + | + | When using one of the framework's cache driven session backends, you may + | define the cache store which should be used to store the session data + | between requests. This must match one of your defined cache stores. + | + | Affects: "apc", "dynamodb", "memcached", "redis" + | + */ + + 'store' => env('SESSION_STORE'), + + /* + |-------------------------------------------------------------------------- + | Session Sweeping Lottery + |-------------------------------------------------------------------------- + | + | Some session drivers must manually sweep their storage location to get + | rid of old sessions from storage. Here are the chances that it will + | happen on a given request. By default, the odds are 2 out of 100. + | + */ + + 'lottery' => [2, 100], + + /* + |-------------------------------------------------------------------------- + | Session Cookie Name + |-------------------------------------------------------------------------- + | + | Here you may change the name of the session cookie that is created by + | the framework. Typically, you should not need to change this value + | since doing so does not grant a meaningful security improvement. + | + */ + + 'cookie' => env( + 'SESSION_COOKIE', + Str::slug(env('APP_NAME', 'laravel'), '_').'_session' + ), + + /* + |-------------------------------------------------------------------------- + | Session Cookie Path + |-------------------------------------------------------------------------- + | + | The session cookie path determines the path for which the cookie will + | be regarded as available. Typically, this will be the root path of + | your application, but you're free to change this when necessary. + | + */ + + 'path' => env('SESSION_PATH', '/'), + + /* + |-------------------------------------------------------------------------- + | Session Cookie Domain + |-------------------------------------------------------------------------- + | + | This value determines the domain and subdomains the session cookie is + | available to. By default, the cookie will be available to the root + | domain and all subdomains. Typically, this shouldn't be changed. + | + */ + + 'domain' => env('SESSION_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | HTTPS Only Cookies + |-------------------------------------------------------------------------- + | + | By setting this option to true, session cookies will only be sent back + | to the server if the browser has a HTTPS connection. This will keep + | the cookie from being sent to you when it can't be done securely. + | + */ + + 'secure' => env('SESSION_SECURE_COOKIE'), + + /* + |-------------------------------------------------------------------------- + | HTTP Access Only + |-------------------------------------------------------------------------- + | + | Setting this value to true will prevent JavaScript from accessing the + | value of the cookie and the cookie will only be accessible through + | the HTTP protocol. It's unlikely you should disable this option. + | + */ + + 'http_only' => env('SESSION_HTTP_ONLY', true), + + /* + |-------------------------------------------------------------------------- + | Same-Site Cookies + |-------------------------------------------------------------------------- + | + | This option determines how your cookies behave when cross-site requests + | take place, and can be used to mitigate CSRF attacks. By default, we + | will set this value to "lax" to permit secure cross-site requests. + | + | See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value + | + | Supported: "lax", "strict", "none", null + | + */ + + 'same_site' => env('SESSION_SAME_SITE', 'lax'), + + /* + |-------------------------------------------------------------------------- + | Partitioned Cookies + |-------------------------------------------------------------------------- + | + | Setting this value to true will tie the cookie to the top-level site for + | a cross-site context. Partitioned cookies are accepted by the browser + | when flagged "secure" and the Same-Site attribute is set to "none". + | + */ + + 'partitioned' => env('SESSION_PARTITIONED_COOKIE', false), + +]; diff --git a/config/sweetalert.php b/config/sweetalert.php new file mode 100644 index 0000000..625e3e4 --- /dev/null +++ b/config/sweetalert.php @@ -0,0 +1,267 @@ + env('SWEET_ALERT_THEME', 'default'), + + /* + |-------------------------------------------------------------------------- + | CDN LINK + |-------------------------------------------------------------------------- + | By default SweetAlert2 use its local sweetalert.all.js + | file. + | However, you can use its cdn if you want. + | + */ + + 'cdn' => env('SWEET_ALERT_CDN'), + + /* + |-------------------------------------------------------------------------- + | Always load the sweetalert.all.js + |-------------------------------------------------------------------------- + | There might be situations where you will always want the sweet alert + | js package to be there for you. (for eg. you might use it heavily to + | show notifications or you might want to use the native js) then this + | might be handy. + | + */ + + 'alwaysLoadJS' => env('SWEET_ALERT_ALWAYS_LOAD_JS', false), + + /* + |-------------------------------------------------------------------------- + | Never load the sweetalert.all.js + |-------------------------------------------------------------------------- + | If you want to handle the sweet alert js package by yourself + | (for eg. you might want to use laravel mix) then this can be + | handy. + | + | alwaysLoadJs = true & neverLoadJs = true => js will not be loaded + | alwaysLoadJs = true & neverLoadJs = false => js will be loaded + | alwaysLoadJs = false & neverLoadJs = false => js will be loaded when + | you set alert/toast by using the facade/helper functions. + */ + + 'neverLoadJS' => env('SWEET_ALERT_NEVER_LOAD_JS', false), + + /* + |-------------------------------------------------------------------------- + | AutoClose Timer + |-------------------------------------------------------------------------- + | + | This is for the all Modal windows. + | For specific modal just use the autoClose() helper method. + | + */ + + 'timer' => env('SWEET_ALERT_TIMER', 5000), + + /* + |-------------------------------------------------------------------------- + | Width + |-------------------------------------------------------------------------- + | + | Modal window width, including paddings (box-sizing: border-box). + | Can be in px or %. + | The default width is 32rem. + | This is for the all Modal windows. + | for particular modal just use the width() helper method. + */ + + 'width' => env('SWEET_ALERT_WIDTH', '32rem'), + + /* + |-------------------------------------------------------------------------- + | Height Auto + |-------------------------------------------------------------------------- + | By default, SweetAlert2 sets html's and body's CSS height to auto !important. + | If this behavior isn't compatible with your project's layout, + | set heightAuto to false. + | + */ + + 'height_auto' => env('SWEET_ALERT_HEIGHT_AUTO', true), + + /* + |-------------------------------------------------------------------------- + | Padding + |-------------------------------------------------------------------------- + | + | Modal window padding. + | Can be in px or %. + | The default padding is 1.25rem. + | This is for the all Modal windows. + | for particular modal just use the padding() helper method. + */ + + 'padding' => env('SWEET_ALERT_PADDING', '1.25rem'), + + /* + |-------------------------------------------------------------------------- + | Background + |-------------------------------------------------------------------------- + | + | Modal window background + | (CSS background property). + | The default background is '#fff'. + */ + + 'background' => env('SWEET_ALERT_BACKGROUND', '#fff'), + + /* + |-------------------------------------------------------------------------- + | Animation + |-------------------------------------------------------------------------- + | Custom animation with [Animate.css](https://daneden.github.io/animate.css/) + | If set to false, modal CSS animation will be use default ones. + | For specific modal just use the animation() helper method. + | + */ + + 'animation' => [ + 'enable' => env('SWEET_ALERT_ANIMATION_ENABLE', false), + ], + + 'animatecss' => env('SWEET_ALERT_ANIMATECSS', 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css'), + + /* + |-------------------------------------------------------------------------- + | ShowConfirmButton + |-------------------------------------------------------------------------- + | If set to false, a "Confirm"-button will not be shown. + | It can be useful when you're using custom HTML description. + | This is for the all Modal windows. + | For specific modal just use the showConfirmButton() helper method. + | + */ + + 'show_confirm_button' => env('SWEET_ALERT_CONFIRM_BUTTON', true), + + /* + |-------------------------------------------------------------------------- + | ShowCloseButton + |-------------------------------------------------------------------------- + | If set to true, a "Close"-button will be shown, + | which the user can click on to dismiss the modal. + | This is for the all Modal windows. + | For specific modal just use the showCloseButton() helper method. + | + */ + + 'show_close_button' => env('SWEET_ALERT_CLOSE_BUTTON', false), + + /* + |----------------------------------------------------------------------- + | Confirm/Cancel Button Text + |----------------------------------------------------------------------- + | Change the default text of the modal buttons. + | The texts translations will be handled by Laravel at runtime. + | This is for the all Modal windows. + | For specific modal just use the confirmButtonText() and + | cancelButtonText() helper methods. + */ + + 'button_text' => [ + 'confirm' => env('SWEET_ALERT_CONFIRM_BUTTON_TEXT', 'OK'), + 'cancel' => env('SWEET_ALERT_CANCEL_BUTTON_TEXT', 'Cancel'), + ], + + /* + |-------------------------------------------------------------------------- + | Toast position + |-------------------------------------------------------------------------- + | Modal window or toast position, can be 'top', + | 'top-start', 'top-end', 'center', 'center-start', + | 'center-end', 'bottom', 'bottom-start', or 'bottom-end'. + | For specific modal just use the position() helper method. + | + */ + + 'toast_position' => env('SWEET_ALERT_TOAST_POSITION', 'top-end'), + + /* + |-------------------------------------------------------------------------- + | Progress Bar + |-------------------------------------------------------------------------- + | If set to true, a progress bar at the bottom of a popup will be shown. + | It can be useful with toasts. + | + */ + + 'timer_progress_bar' => env('SWEET_ALERT_TIMER_PROGRESS_BAR', false), + + /* + |-------------------------------------------------------------------------- + | Middleware + |-------------------------------------------------------------------------- + | Modal window or toast, config for the Middleware + | + */ + + 'middleware' => [ + + 'autoClose' => env('SWEET_ALERT_MIDDLEWARE_AUTO_CLOSE', false), + + 'toast_position' => env('SWEET_ALERT_MIDDLEWARE_TOAST_POSITION', 'top-end'), + + 'toast_close_button' => env('SWEET_ALERT_MIDDLEWARE_TOAST_CLOSE_BUTTON', true), + + 'timer' => env('SWEET_ALERT_MIDDLEWARE_ALERT_CLOSE_TIME', 6000), + + 'auto_display_error_messages' => env('SWEET_ALERT_AUTO_DISPLAY_ERROR_MESSAGES', true), + ], + + /* + |-------------------------------------------------------------------------- + | Custom Class + |-------------------------------------------------------------------------- + | A custom CSS class for the modal: + | + */ + + 'customClass' => [ + + 'container' => env('SWEET_ALERT_CONTAINER_CLASS'), + 'popup' => env('SWEET_ALERT_POPUP_CLASS'), + 'header' => env('SWEET_ALERT_HEADER_CLASS'), + 'title' => env('SWEET_ALERT_TITLE_CLASS'), + 'closeButton' => env('SWEET_ALERT_CLOSE_BUTTON_CLASS'), + 'icon' => env('SWEET_ALERT_ICON_CLASS'), + 'image' => env('SWEET_ALERT_IMAGE_CLASS'), + 'content' => env('SWEET_ALERT_CONTENT_CLASS'), + 'input' => env('SWEET_ALERT_INPUT_CLASS'), + 'actions' => env('SWEET_ALERT_ACTIONS_CLASS'), + 'confirmButton' => env('SWEET_ALERT_CONFIRM_BUTTON_CLASS'), + 'cancelButton' => env('SWEET_ALERT_CANCEL_BUTTON_CLASS'), + 'footer' => env('SWEET_ALERT_FOOTER_CLASS'), + ], + + /* + |-------------------------------------------------------------------------- + | confirmDelete + |-------------------------------------------------------------------------- + | customize the configuration options of the confirmation popup. + | + */ + + 'confirm_delete_confirm_button_text' => env('SWEET_ALERT_CONFIRM_DELETE_CONFIRM_BUTTON_TEXT', 'Yes, delete it!'), + 'confirm_delete_confirm_button_color' => env('SWEET_ALERT_CONFIRM_DELETE_CONFIRM_BUTTON_COLOR'), + 'confirm_delete_cancel_button_color' => env('SWEET_ALERT_CONFIRM_DELETE_CANCEL_BUTTON_COLOR', '#d33'), + 'confirm_delete_cancel_button_text' => env('SWEET_ALERT_CONFIRM_DELETE_CANCEL_BUTTON_TEXT', 'Cancel'), + 'confirm_delete_show_cancel_button' => env('SWEET_ALERT_CONFIRM_DELETE_SHOW_CANCEL_BUTTON', true), + 'confirm_delete_show_close_button' => env('SWEET_ALERT_CONFIRM_DELETE_SHOW_CLOSE_BUTTON', false), + 'confirm_delete_icon' => env('SWEET_ALERT_CONFIRM_DELETE_ICON', 'warning'), + 'confirm_delete_show_loader_on_confirm' => env('SWEET_ALERT_CONFIRM_DELETE_SHOW_LOADER_ON_CONFIRM', true), + + +]; diff --git a/database/.gitignore b/database/.gitignore new file mode 100644 index 0000000..9b19b93 --- /dev/null +++ b/database/.gitignore @@ -0,0 +1 @@ +*.sqlite* diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php new file mode 100644 index 0000000..584104c --- /dev/null +++ b/database/factories/UserFactory.php @@ -0,0 +1,44 @@ + + */ +class UserFactory extends Factory +{ + /** + * The current password being used by the factory. + */ + protected static ?string $password; + + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + 'name' => fake()->name(), + 'email' => fake()->unique()->safeEmail(), + 'email_verified_at' => now(), + 'password' => static::$password ??= Hash::make('password'), + 'remember_token' => Str::random(10), + ]; + } + + /** + * Indicate that the model's email address should be unverified. + */ + public function unverified(): static + { + return $this->state(fn (array $attributes) => [ + 'email_verified_at' => null, + ]); + } +} diff --git a/database/migrations/2025_04_06_041010_create_tahun_ajaran_table.php b/database/migrations/2025_04_06_041010_create_tahun_ajaran_table.php new file mode 100644 index 0000000..c800b13 --- /dev/null +++ b/database/migrations/2025_04_06_041010_create_tahun_ajaran_table.php @@ -0,0 +1,27 @@ +String('tahun', 9)->primary(); + $table->enum('status', ['aktif', 'selesai']); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('tahun_ajaran'); + } +}; diff --git a/database/migrations/2025_04_06_041050_create_users_table.php b/database/migrations/2025_04_06_041050_create_users_table.php new file mode 100644 index 0000000..506743a --- /dev/null +++ b/database/migrations/2025_04_06_041050_create_users_table.php @@ -0,0 +1,29 @@ +id(); + $table->String('email'); + $table->String('password'); + $table->enum('role', ['admin', 'guru', 'siswa']); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users'); + } +}; diff --git a/database/migrations/2025_04_06_041203_create_admin_table.php b/database/migrations/2025_04_06_041203_create_admin_table.php new file mode 100644 index 0000000..65c7d59 --- /dev/null +++ b/database/migrations/2025_04_06_041203_create_admin_table.php @@ -0,0 +1,36 @@ +id(); + $table->unsignedBigInteger("user_id"); + $table->String("nip", 18)->unique(); + $table->String("nama", 100); + $table->enum("jk", ["L", "P"]); + $table->timestamps(); + + $table->foreign('user_id') + ->references('id') + ->on('users') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('admin'); + } +}; diff --git a/database/migrations/2025_04_06_041210_create_guru_table.php b/database/migrations/2025_04_06_041210_create_guru_table.php new file mode 100644 index 0000000..e083956 --- /dev/null +++ b/database/migrations/2025_04_06_041210_create_guru_table.php @@ -0,0 +1,36 @@ +id(); + $table->unsignedBigInteger("user_id"); + $table->String("nip", 18)->unique(); + $table->String("nama", 100); + $table->enum("jk", ["L", "P"]); + $table->timestamps(); + + $table->foreign('user_id') + ->references('id') + ->on('users') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('guru'); + } +}; diff --git a/database/migrations/2025_04_06_041748_create_kelas_table.php b/database/migrations/2025_04_06_041748_create_kelas_table.php new file mode 100644 index 0000000..53f1ab7 --- /dev/null +++ b/database/migrations/2025_04_06_041748_create_kelas_table.php @@ -0,0 +1,33 @@ +String("nama", 10)->primary(); + $table->String("nip_wali", 18); + $table->timestamps(); + + $table->foreign('nip_wali') + ->references('nip') + ->on('guru') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('kelas'); + } +}; diff --git a/database/migrations/2025_04_06_042443_create_siswa_table.php b/database/migrations/2025_04_06_042443_create_siswa_table.php new file mode 100644 index 0000000..ac3af4d --- /dev/null +++ b/database/migrations/2025_04_06_042443_create_siswa_table.php @@ -0,0 +1,50 @@ +id(); + $table->unsignedBigInteger("user_id"); + $table->String("nisn", 12)->unique(); + $table->String("nama", 100); + $table->enum("jk", ["L", "P"]); + $table->String("kelas", 10); + $table->String("tahun_ajaran", 9); + $table->timestamps(); + + $table->foreign('user_id') + ->references('id') + ->on('users') + ->onUpdate('cascade') + ->onDelete('cascade'); + + $table->foreign('kelas') + ->references('nama') + ->on('kelas') + ->onUpdate('cascade') + ->onDelete('cascade'); + + $table->foreign('tahun_ajaran') + ->references('tahun') + ->on('tahun_ajaran') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('siswa'); + } +}; diff --git a/database/migrations/2025_04_06_043020_create_matapelajaran_table.php b/database/migrations/2025_04_06_043020_create_matapelajaran_table.php new file mode 100644 index 0000000..bee7b61 --- /dev/null +++ b/database/migrations/2025_04_06_043020_create_matapelajaran_table.php @@ -0,0 +1,48 @@ +id(); + $table->String("nama", 100); + $table->String("guru_nip", 18); + $table->String("kelas", 10); + $table->String("tahun_ajaran", 9); + $table->timestamps(); + + $table->foreign('guru_nip') + ->references('nip') + ->on('guru') + ->onUpdate('cascade') + ->onDelete('cascade'); + + $table->foreign('kelas') + ->references('nama') + ->on('kelas') + ->onUpdate('cascade') + ->onDelete('cascade'); + + $table->foreign('tahun_ajaran') + ->references('tahun') + ->on('tahun_ajaran') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('matapelajaran'); + } +}; diff --git a/database/migrations/2025_04_06_043328_create_tugas_table.php b/database/migrations/2025_04_06_043328_create_tugas_table.php new file mode 100644 index 0000000..acb52e5 --- /dev/null +++ b/database/migrations/2025_04_06_043328_create_tugas_table.php @@ -0,0 +1,50 @@ +id(); + $table->date("tanggal"); + $table->date("tenggat"); + $table->text("nama"); + $table->unsignedBigInteger("matapelajaran_id"); + $table->String("kelas", 10); + $table->String("tahun_ajaran", 9); + $table->timestamps(); + + $table->foreign('matapelajaran_id') + ->references('id') + ->on('matapelajaran') + ->onUpdate('cascade') + ->onDelete('cascade'); + + $table->foreign('kelas') + ->references('nama') + ->on('kelas') + ->onUpdate('cascade') + ->onDelete('cascade'); + + $table->foreign('tahun_ajaran') + ->references('tahun') + ->on('tahun_ajaran') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('tugas'); + } +}; diff --git a/database/migrations/2025_04_06_044101_create_submit_tugas_table.php b/database/migrations/2025_04_06_044101_create_submit_tugas_table.php new file mode 100644 index 0000000..53213b9 --- /dev/null +++ b/database/migrations/2025_04_06_044101_create_submit_tugas_table.php @@ -0,0 +1,43 @@ +id(); + $table->date("tanggal"); + $table->String("nisn", 12); + $table->unsignedBigInteger("tugas_id"); + $table->text("text")->nullable(true); + $table->String("file")->nullable(true); + $table->timestamps(); + + $table->foreign('nisn') + ->references('nisn') + ->on('siswa') + ->onUpdate('cascade') + ->onDelete('cascade'); + + $table->foreign('tugas_id') + ->references('id') + ->on('tugas') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('submit_tugaas'); + } +}; diff --git a/database/migrations/2025_04_06_044510_create_materi_table.php b/database/migrations/2025_04_06_044510_create_materi_table.php new file mode 100644 index 0000000..a0f5dc2 --- /dev/null +++ b/database/migrations/2025_04_06_044510_create_materi_table.php @@ -0,0 +1,46 @@ +id(); + $table->date("tanggal"); + $table->unsignedBigInteger("matapelajaran_id"); + $table->enum("semester", ["1", "2"]); + $table->enum("type", ["buku", "video"]); + $table->string("judul_materi"); + $table->text("deskripsi"); + $table->String("path"); + $table->String("tahun_ajaran", 9); + $table->timestamps(); + + $table->foreign('matapelajaran_id') + ->references('id') + ->on('matapelajaran') + ->onUpdate('cascade') + ->onDelete('cascade'); + + $table->foreign('tahun_ajaran') + ->references('tahun') + ->on('tahun_ajaran') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('materi'); + } +}; diff --git a/database/migrations/2025_04_07_020934_create_sessions_table.php b/database/migrations/2025_04_07_020934_create_sessions_table.php new file mode 100644 index 0000000..f2251ee --- /dev/null +++ b/database/migrations/2025_04_07_020934_create_sessions_table.php @@ -0,0 +1,30 @@ +string('id')->primary(); + $table->foreignId('user_id')->nullable()->index(); + $table->string('ip_address', 45)->nullable(); + $table->text('user_agent')->nullable(); + $table->longText('payload'); + $table->integer('last_activity')->index(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('sessions'); + } +}; diff --git a/database/migrations/2025_04_09_041911_update_column_kelas_table.php b/database/migrations/2025_04_09_041911_update_column_kelas_table.php new file mode 100644 index 0000000..2547554 --- /dev/null +++ b/database/migrations/2025_04_09_041911_update_column_kelas_table.php @@ -0,0 +1,34 @@ +dropForeign(['nip_wali']); + $table->dropColumn('nip_wali'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('kelas', function (Blueprint $table) { + $table->String("nip_wali", 18)->after('nama'); + + $table->foreign('nip_wali') + ->references('nip') + ->on('guru') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } +}; diff --git a/database/migrations/2025_04_09_042116_create_riwayat_kelas_table.php b/database/migrations/2025_04_09_042116_create_riwayat_kelas_table.php new file mode 100644 index 0000000..9658100 --- /dev/null +++ b/database/migrations/2025_04_09_042116_create_riwayat_kelas_table.php @@ -0,0 +1,47 @@ +id(); + $table->String("kelas", 10); + $table->string("tahun_ajaran", 9); + $table->String("wali_nip", 18); + $table->timestamps(); + + $table->foreign('kelas') + ->references('nama') + ->on('kelas') + ->onUpdate('cascade') + ->onDelete('cascade'); + + $table->foreign('wali_nip') + ->references('nip') + ->on('guru') + ->onUpdate('cascade') + ->onDelete('cascade'); + + $table->foreign('tahun_ajaran') + ->references('tahun') + ->on('tahun_ajaran') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('riwayat_kelas'); + } +}; diff --git a/database/migrations/2025_04_13_040415_update_column_tugas_table.php b/database/migrations/2025_04_13_040415_update_column_tugas_table.php new file mode 100644 index 0000000..e8a888b --- /dev/null +++ b/database/migrations/2025_04_13_040415_update_column_tugas_table.php @@ -0,0 +1,33 @@ +string('guru_nip', 18)->after('tenggat'); + $table->foreign('guru_nip') + ->references('nip') + ->on('guru') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('tugas', function (Blueprint $table) { + $table->dropForeign(['guru_nip']); + $table->dropColumn('guru_nip', 18); + }); + } +}; diff --git a/database/migrations/2025_04_13_090139_create_personal_access_tokens_table.php b/database/migrations/2025_04_13_090139_create_personal_access_tokens_table.php new file mode 100644 index 0000000..82dbff5 --- /dev/null +++ b/database/migrations/2025_04_13_090139_create_personal_access_tokens_table.php @@ -0,0 +1,32 @@ +id(); + $table->morphs('tokenable'); + $table->string('name'); + $table->string('token', 64)->unique(); + $table->text('abilities')->nullable(); + $table->timestamp('last_used_at')->nullable(); + $table->timestamp('expires_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('personal_access_tokens'); + } +}; diff --git a/database/migrations/2025_04_14_000000_add_nilai_to_submit_tugas_table.php b/database/migrations/2025_04_14_000000_add_nilai_to_submit_tugas_table.php new file mode 100644 index 0000000..00765ec --- /dev/null +++ b/database/migrations/2025_04_14_000000_add_nilai_to_submit_tugas_table.php @@ -0,0 +1,27 @@ +integer('nilai')->nullable()->after('file'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('submit_tugas', function (Blueprint $table) { + $table->dropColumn('nilai'); + }); + } +}; \ No newline at end of file diff --git a/database/migrations/2025_04_19_060119_create_quizzes_table.php b/database/migrations/2025_04_19_060119_create_quizzes_table.php new file mode 100644 index 0000000..54547f1 --- /dev/null +++ b/database/migrations/2025_04_19_060119_create_quizzes_table.php @@ -0,0 +1,37 @@ +id(); + $table->string('judul')->comment('Nama Kuis'); + $table->text('deskripsi')->nullable(); + $table->integer('total_soal')->comment('Jumlah soal Maksimal'); + $table->unsignedBigInteger("matapelajaran_id"); + $table->timestamps(); + + $table->foreign('matapelajaran_id') + ->references('id') + ->on('matapelajaran') + ->onUpdate('cascade') + ->onDelete('cascade'); + + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('quizzes'); + } +}; diff --git a/database/migrations/2025_04_19_060933_create_quiz_questions_table.php b/database/migrations/2025_04_19_060933_create_quiz_questions_table.php new file mode 100644 index 0000000..c4b86d1 --- /dev/null +++ b/database/migrations/2025_04_19_060933_create_quiz_questions_table.php @@ -0,0 +1,40 @@ +id(); + $table->unsignedBigInteger("quiz_id"); + $table->text("pertanyaan"); + $table->string("opsi_a"); + $table->string("opsi_b"); + $table->string("opsi_c"); + $table->string("opsi_d"); + $table->string("jawaban_benar", 5); + $table->integer("level")->comment("Level Soal"); + $table->timestamps(); + + $table->foreign('quiz_id') + ->references('id') + ->on('quizzes') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('quiz_questions'); + } +}; diff --git a/database/migrations/2025_04_19_061824_create_quiz_attempts_table.php b/database/migrations/2025_04_19_061824_create_quiz_attempts_table.php new file mode 100644 index 0000000..f61bb7a --- /dev/null +++ b/database/migrations/2025_04_19_061824_create_quiz_attempts_table.php @@ -0,0 +1,42 @@ +id(); + $table->unsignedBigInteger("quiz_id"); + $table->String("nisn", 12); + $table->String("skor")->comment("skor akhir"); + $table->integer("level_akhir")->comment("Level terakhir yang dicapai siswa"); + $table->timestamps(); + + $table->foreign('quiz_id') + ->references('id') + ->on('quizzes') + ->onUpdate('cascade') + ->onDelete('cascade'); + + $table->foreign('nisn') + ->references('nisn') + ->on('siswa') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('quiz_attempts'); + } +}; diff --git a/database/migrations/2025_04_19_061836_create_quiz_attempt_answers_table.php b/database/migrations/2025_04_19_061836_create_quiz_attempt_answers_table.php new file mode 100644 index 0000000..926f039 --- /dev/null +++ b/database/migrations/2025_04_19_061836_create_quiz_attempt_answers_table.php @@ -0,0 +1,42 @@ +id(); + $table->unsignedBigInteger("attempt_id"); + $table->unsignedBigInteger("question_id"); + $table->char("jawaban_siswa", 1); + $table->boolean("benar"); + $table->timestamps(); + + $table->foreign('attempt_id') + ->references('id') + ->on('quiz_attempts') + ->onUpdate('cascade') + ->onDelete('cascade'); + + $table->foreign('question_id') + ->references('id') + ->on('quiz_questions') + ->onUpdate('cascade') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('quiz_attempt_answers'); + } +}; diff --git a/database/migrations/2025_04_28_123932_update_quizzes_table.php b/database/migrations/2025_04_28_123932_update_quizzes_table.php new file mode 100644 index 0000000..0f86356 --- /dev/null +++ b/database/migrations/2025_04_28_123932_update_quizzes_table.php @@ -0,0 +1,27 @@ +string('total_soal_tampil', 11)->after('total_soal'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('quizzes', function (Blueprint $table) { + $table->dropColumn('total_soal_tampil'); + }); + } +}; diff --git a/database/migrations/2025_04_29_025446_add_jumlah_soal_dijawab_to_quiz_attempts_table.php b/database/migrations/2025_04_29_025446_add_jumlah_soal_dijawab_to_quiz_attempts_table.php new file mode 100644 index 0000000..be3c09a --- /dev/null +++ b/database/migrations/2025_04_29_025446_add_jumlah_soal_dijawab_to_quiz_attempts_table.php @@ -0,0 +1,30 @@ +integer('jumlah_soal_dijawab')->default(0)->after('level_akhir'); + $table->integer('benar_fase1')->default(0)->after('jumlah_soal_dijawab'); + $table->integer('benar_fase2')->default(0)->after('benar_fase1'); + $table->integer('fase')->default(1)->after('benar_fase2'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('quiz_attempts', function (Blueprint $table) { + $table->dropColumn(['jumlah_soal_dijawab', 'benar_fase1', 'benar_fase2', 'fase']); + }); + } +}; diff --git a/database/migrations/2025_05_01_113324_create_notifications_table.php b/database/migrations/2025_05_01_113324_create_notifications_table.php new file mode 100644 index 0000000..d738032 --- /dev/null +++ b/database/migrations/2025_05_01_113324_create_notifications_table.php @@ -0,0 +1,31 @@ +uuid('id')->primary(); + $table->string('type'); + $table->morphs('notifiable'); + $table->text('data'); + $table->timestamp('read_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('notifications'); + } +}; diff --git a/database/migrations/2025_05_14_135306_create_quiz_level_settings_table.php b/database/migrations/2025_05_14_135306_create_quiz_level_settings_table.php new file mode 100644 index 0000000..c8d7e1e --- /dev/null +++ b/database/migrations/2025_05_14_135306_create_quiz_level_settings_table.php @@ -0,0 +1,31 @@ +id(); + $table->foreignId('quiz_id')->constrained('quizzes')->onDelete('cascade'); + $table->json('jumlah_soal_per_level'); + $table->integer('level_awal')->default(1); + $table->json('batas_naik_level')->nullable(true); + $table->integer('kkm')->default(70); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('quiz_level_settings'); + } +}; diff --git a/database/migrations/2025_05_17_041523_update_quiz_attempts_table.php b/database/migrations/2025_05_17_041523_update_quiz_attempts_table.php new file mode 100644 index 0000000..0f15321 --- /dev/null +++ b/database/migrations/2025_05_17_041523_update_quiz_attempts_table.php @@ -0,0 +1,33 @@ +dropColumn('benar_fase1'); + $table->dropColumn('benar_fase2'); + $table->dropColumn('fase'); + $table->json('benar')->nullable()->after('jumlah_soal_dijawab'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('quiz_attempts', function (Blueprint $table) { + $table->integer('benar_fase1')->default(0)->after('jumlah_soal_dijawab'); + $table->integer('benar_fase2')->default(0)->after('benar_fase1'); + $table->integer('fase')->default(1)->after('benar_fase2'); + $table->dropColumn('benar'); + }); + } +}; diff --git a/database/migrations/2025_05_17_083327_update_quiz_questions_table.php b/database/migrations/2025_05_17_083327_update_quiz_questions_table.php new file mode 100644 index 0000000..5b61828 --- /dev/null +++ b/database/migrations/2025_05_17_083327_update_quiz_questions_table.php @@ -0,0 +1,27 @@ +integer('skor')->default(10)->after('level'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('quiz_questions', function (Blueprint $table) { + $table->dropColumn('skor'); + }); + } +}; diff --git a/database/migrations/2025_05_17_112603_update_quiz_attempts_table.php b/database/migrations/2025_05_17_112603_update_quiz_attempts_table.php new file mode 100644 index 0000000..e165869 --- /dev/null +++ b/database/migrations/2025_05_17_112603_update_quiz_attempts_table.php @@ -0,0 +1,27 @@ +integer('fase')->default(1)->after('jumlah_soal_dijawab'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('quiz_attempts', function (Blueprint $table) { + $table->dropColumn('fase'); + }); + } +}; diff --git a/database/migrations/2025_05_18_072836_update_quiz_level_settings_table.php b/database/migrations/2025_05_18_072836_update_quiz_level_settings_table.php new file mode 100644 index 0000000..bd9cc3e --- /dev/null +++ b/database/migrations/2025_05_18_072836_update_quiz_level_settings_table.php @@ -0,0 +1,27 @@ +json('skor_level')->after('batas_naik_level'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('quiz_level_settings', function (Blueprint $table) { + $table->dropColumn('skor_level'); + }); + } +}; diff --git a/database/migrations/2025_05_25_065949_create_cache_tables.php b/database/migrations/2025_05_25_065949_create_cache_tables.php new file mode 100644 index 0000000..b9c106b --- /dev/null +++ b/database/migrations/2025_05_25_065949_create_cache_tables.php @@ -0,0 +1,35 @@ +string('key')->primary(); + $table->mediumText('value'); + $table->integer('expiration'); + }); + + Schema::create('cache_locks', function (Blueprint $table) { + $table->string('key')->primary(); + $table->string('owner'); + $table->integer('expiration'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('cache'); + Schema::dropIfExists('cache_locks'); + } +}; diff --git a/database/migrations/2025_06_14_230738_add_waktu_to_quizzes_table.php b/database/migrations/2025_06_14_230738_add_waktu_to_quizzes_table.php new file mode 100644 index 0000000..bb0678d --- /dev/null +++ b/database/migrations/2025_06_14_230738_add_waktu_to_quizzes_table.php @@ -0,0 +1,28 @@ +integer('waktu')->nullable()->after('total_soal_tampil')->comment('Waktu pengerjaan quiz dalam menit'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('quizzes', function (Blueprint $table) { + $table->dropColumn('waktu'); + }); + } +}; diff --git a/database/migrations/2025_06_15_023329_add_timing_to_quiz_attempts_table.php b/database/migrations/2025_06_15_023329_add_timing_to_quiz_attempts_table.php new file mode 100644 index 0000000..5a8d5f0 --- /dev/null +++ b/database/migrations/2025_06_15_023329_add_timing_to_quiz_attempts_table.php @@ -0,0 +1,28 @@ +string('nip_wali', 18)->nullable(); + }); + } + + public function down(): void + { + Schema::table('kelas', function (Blueprint $table) { + $table->dropColumn('nip_wali'); + }); + } +}; diff --git a/database/migrations/2025_07_09_000000_create_audit_logs_table.php b/database/migrations/2025_07_09_000000_create_audit_logs_table.php new file mode 100644 index 0000000..661c02a --- /dev/null +++ b/database/migrations/2025_07_09_000000_create_audit_logs_table.php @@ -0,0 +1,23 @@ +id(); + $table->unsignedBigInteger('user_id')->nullable(); + $table->string('action'); + $table->text('description')->nullable(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('audit_logs'); + } +}; \ No newline at end of file diff --git a/database/migrations/2025_07_09_032625_update_tenggat_column_on_tugas_table.php b/database/migrations/2025_07_09_032625_update_tenggat_column_on_tugas_table.php new file mode 100644 index 0000000..36ef8f2 --- /dev/null +++ b/database/migrations/2025_07_09_032625_update_tenggat_column_on_tugas_table.php @@ -0,0 +1,28 @@ +dateTime('tenggat')->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('tugas', function (Blueprint $table) { + $table->date('tenggat')->change(); + }); + } +}; diff --git a/database/migrations/2025_07_09_035728_update_tanggal_column_on_materi_table.php b/database/migrations/2025_07_09_035728_update_tanggal_column_on_materi_table.php new file mode 100644 index 0000000..f5176f3 --- /dev/null +++ b/database/migrations/2025_07_09_035728_update_tanggal_column_on_materi_table.php @@ -0,0 +1,28 @@ +dateTime('tanggal')->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('materi', function (Blueprint $table) { + $table->date('tanggal')->change(); + }); + } +}; diff --git a/database/migrations/2025_07_15_000000_add_deskripsi_to_tugas_table.php b/database/migrations/2025_07_15_000000_add_deskripsi_to_tugas_table.php new file mode 100644 index 0000000..fb44cbf --- /dev/null +++ b/database/migrations/2025_07_15_000000_add_deskripsi_to_tugas_table.php @@ -0,0 +1,19 @@ +text('deskripsi')->nullable()->after('nama'); + }); + } + public function down() + { + Schema::table('tugas', function (Blueprint $table) { + $table->dropColumn('deskripsi'); + }); + } +}; \ No newline at end of file diff --git a/database/seeders/AdminSeeder.php b/database/seeders/AdminSeeder.php new file mode 100644 index 0000000..a799e57 --- /dev/null +++ b/database/seeders/AdminSeeder.php @@ -0,0 +1,31 @@ + 'admin@gmail.com', + 'password' => Hash::make('12345'), + 'role' => 'admin', + ]); + + Admin::create([ + 'user_id' => $user->id, + 'nip' => '123456789', + 'nama' => 'Admin SD', + 'jk' => 'L', + ]); + } +} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php new file mode 100644 index 0000000..3cd7eaa --- /dev/null +++ b/database/seeders/DatabaseSeeder.php @@ -0,0 +1,26 @@ +create(); + + $this->call([ + AdminSeeder::class, + KelasSeeder::class, + TahunAjaranSeeder::class, + ]); + } +} diff --git a/database/seeders/KelasSeeder.php b/database/seeders/KelasSeeder.php new file mode 100644 index 0000000..4e5b259 --- /dev/null +++ b/database/seeders/KelasSeeder.php @@ -0,0 +1,24 @@ + $value, + ]); + } + } +} diff --git a/database/seeders/TahunAjaranSeeder.php b/database/seeders/TahunAjaranSeeder.php new file mode 100644 index 0000000..f0ba800 --- /dev/null +++ b/database/seeders/TahunAjaranSeeder.php @@ -0,0 +1,25 @@ + $value, + 'status' => 'aktif', + ]); + } + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..0759bba --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3966 @@ +{ + "name": "elearning-deploy", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@heroicons/react": "^2.2.0", + "@tailwindcss/vite": "^4.1.3", + "flowbite": "^3.1.2" + }, + "devDependencies": { + "autoprefixer": "^10.4.21", + "axios": "^1.7.4", + "concurrently": "^9.0.1", + "laravel-vite-plugin": "^1.2.0", + "postcss": "^8.5.3", + "tailwindcss": "^3.4.17", + "vite": "^6.0.11" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", + "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", + "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", + "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", + "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", + "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", + "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", + "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", + "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", + "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", + "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", + "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", + "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", + "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", + "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", + "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", + "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", + "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", + "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", + "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", + "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", + "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", + "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", + "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", + "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", + "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@heroicons/react": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz", + "integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==", + "license": "MIT", + "peerDependencies": { + "react": ">= 16 || ^19.0.0-rc" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", + "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", + "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz", + "integrity": "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz", + "integrity": "sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz", + "integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz", + "integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz", + "integrity": "sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz", + "integrity": "sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz", + "integrity": "sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz", + "integrity": "sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz", + "integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz", + "integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz", + "integrity": "sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz", + "integrity": "sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz", + "integrity": "sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz", + "integrity": "sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz", + "integrity": "sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz", + "integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz", + "integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz", + "integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz", + "integrity": "sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz", + "integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.7.tgz", + "integrity": "sha512-9rsOpdY9idRI2NH6CL4wORFY0+Q6fnx9XP9Ju+iq/0wJwGD5IByIgFmwVbyy4ymuyprj8Qh4ErxMKTUL4uNh3g==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "lightningcss": "1.30.1", + "magic-string": "^0.30.17", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.7" + } + }, + "node_modules/@tailwindcss/node/node_modules/tailwindcss": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.7.tgz", + "integrity": "sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==", + "license": "MIT" + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.7.tgz", + "integrity": "sha512-5SF95Ctm9DFiUyjUPnDGkoKItPX/k+xifcQhcqX5RA85m50jw1pT/KzjdvlqxRja45Y52nR4MR9fD1JYd7f8NQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.7", + "@tailwindcss/oxide-darwin-arm64": "4.1.7", + "@tailwindcss/oxide-darwin-x64": "4.1.7", + "@tailwindcss/oxide-freebsd-x64": "4.1.7", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.7", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.7", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.7", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.7", + "@tailwindcss/oxide-linux-x64-musl": "4.1.7", + "@tailwindcss/oxide-wasm32-wasi": "4.1.7", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.7", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.7" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.7.tgz", + "integrity": "sha512-IWA410JZ8fF7kACus6BrUwY2Z1t1hm0+ZWNEzykKmMNM09wQooOcN/VXr0p/WJdtHZ90PvJf2AIBS/Ceqx1emg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.7.tgz", + "integrity": "sha512-81jUw9To7fimGGkuJ2W5h3/oGonTOZKZ8C2ghm/TTxbwvfSiFSDPd6/A/KE2N7Jp4mv3Ps9OFqg2fEKgZFfsvg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.7.tgz", + "integrity": "sha512-q77rWjEyGHV4PdDBtrzO0tgBBPlQWKY7wZK0cUok/HaGgbNKecegNxCGikuPJn5wFAlIywC3v+WMBt0PEBtwGw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.7.tgz", + "integrity": "sha512-RfmdbbK6G6ptgF4qqbzoxmH+PKfP4KSVs7SRlTwcbRgBwezJkAO3Qta/7gDy10Q2DcUVkKxFLXUQO6J3CRvBGw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.7.tgz", + "integrity": "sha512-OZqsGvpwOa13lVd1z6JVwQXadEobmesxQ4AxhrwRiPuE04quvZHWn/LnihMg7/XkN+dTioXp/VMu/p6A5eZP3g==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.7.tgz", + "integrity": "sha512-voMvBTnJSfKecJxGkoeAyW/2XRToLZ227LxswLAwKY7YslG/Xkw9/tJNH+3IVh5bdYzYE7DfiaPbRkSHFxY1xA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.7.tgz", + "integrity": "sha512-PjGuNNmJeKHnP58M7XyjJyla8LPo+RmwHQpBI+W/OxqrwojyuCQ+GUtygu7jUqTEexejZHr/z3nBc/gTiXBj4A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.7.tgz", + "integrity": "sha512-HMs+Va+ZR3gC3mLZE00gXxtBo3JoSQxtu9lobbZd+DmfkIxR54NO7Z+UQNPsa0P/ITn1TevtFxXTpsRU7qEvWg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.7.tgz", + "integrity": "sha512-MHZ6jyNlutdHH8rd+YTdr3QbXrHXqwIhHw9e7yXEBcQdluGwhpQY2Eku8UZK6ReLaWtQ4gijIv5QoM5eE+qlsA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.7.tgz", + "integrity": "sha512-ANaSKt74ZRzE2TvJmUcbFQ8zS201cIPxUDm5qez5rLEwWkie2SkGtA4P+GPTj+u8N6JbPrC8MtY8RmJA35Oo+A==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@emnapi/wasi-threads": "^1.0.2", + "@napi-rs/wasm-runtime": "^0.2.9", + "@tybys/wasm-util": "^0.9.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.7.tgz", + "integrity": "sha512-HUiSiXQ9gLJBAPCMVRk2RT1ZrBjto7WvqsPBwUrNK2BcdSxMnk19h4pjZjI7zgPhDxlAbJSumTC4ljeA9y0tEw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.7.tgz", + "integrity": "sha512-rYHGmvoHiLJ8hWucSfSOEmdCBIGZIq7SpkPRSqLsH2Ab2YUNgKeAPT1Fi2cx3+hnYOrAb0jp9cRyode3bBW4mQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.7.tgz", + "integrity": "sha512-tYa2fO3zDe41I7WqijyVbRd8oWT0aEID1Eokz5hMT6wShLIHj3yvwj9XbfuloHP9glZ6H+aG2AN/+ZrxJ1Y5RQ==", + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.1.7", + "@tailwindcss/oxide": "4.1.7", + "tailwindcss": "4.1.7" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6" + } + }, + "node_modules/@tailwindcss/vite/node_modules/tailwindcss": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.7.tgz", + "integrity": "sha512-kr1o/ErIdNhTz8uzAYL7TpaUuzKIE6QPQ4qmSdxnoX/lo+5wmUHQA6h3L5yIqEImSRnAAURDirLu/BgiXGPAhg==", + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "license": "MIT" + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "license": "MIT" + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.4.21", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz", + "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.24.4", + "caniuse-lite": "^1.0.30001702", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/axios": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", + "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001716", + "electron-to-chromium": "^1.5.149", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001718", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", + "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concurrently": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.1.2.tgz", + "integrity": "sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.157", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.157.tgz", + "integrity": "sha512-/0ybgsQd1muo8QlnuTpKwtl0oX5YMlUGbm8xyqgDU00motRkKFFbUJySAQBWcY79rVqNLWIWa87BGVGClwAB2w==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", + "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.4", + "@esbuild/android-arm": "0.25.4", + "@esbuild/android-arm64": "0.25.4", + "@esbuild/android-x64": "0.25.4", + "@esbuild/darwin-arm64": "0.25.4", + "@esbuild/darwin-x64": "0.25.4", + "@esbuild/freebsd-arm64": "0.25.4", + "@esbuild/freebsd-x64": "0.25.4", + "@esbuild/linux-arm": "0.25.4", + "@esbuild/linux-arm64": "0.25.4", + "@esbuild/linux-ia32": "0.25.4", + "@esbuild/linux-loong64": "0.25.4", + "@esbuild/linux-mips64el": "0.25.4", + "@esbuild/linux-ppc64": "0.25.4", + "@esbuild/linux-riscv64": "0.25.4", + "@esbuild/linux-s390x": "0.25.4", + "@esbuild/linux-x64": "0.25.4", + "@esbuild/netbsd-arm64": "0.25.4", + "@esbuild/netbsd-x64": "0.25.4", + "@esbuild/openbsd-arm64": "0.25.4", + "@esbuild/openbsd-x64": "0.25.4", + "@esbuild/sunos-x64": "0.25.4", + "@esbuild/win32-arm64": "0.25.4", + "@esbuild/win32-ia32": "0.25.4", + "@esbuild/win32-x64": "0.25.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flowbite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/flowbite/-/flowbite-3.1.2.tgz", + "integrity": "sha512-MkwSgbbybCYgMC+go6Da5idEKUFfMqc/AmSjm/2ZbdmvoKf5frLPq/eIhXc9P+rC8t9boZtUXzHDgt5whZ6A/Q==", + "license": "MIT", + "dependencies": { + "@popperjs/core": "^2.9.3", + "flowbite-datepicker": "^1.3.1", + "mini-svg-data-uri": "^1.4.3", + "postcss": "^8.5.1" + } + }, + "node_modules/flowbite-datepicker": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/flowbite-datepicker/-/flowbite-datepicker-1.3.2.tgz", + "integrity": "sha512-6Nfm0MCVX3mpaR7YSCjmEO2GO8CDt6CX8ZpQnGdeu03WUCWtEPQ/uy0PUiNtIJjJZWnX0Cm3H55MOhbD1g+E/g==", + "license": "MIT", + "dependencies": { + "@rollup/plugin-node-resolve": "^15.2.3", + "flowbite": "^2.0.0" + } + }, + "node_modules/flowbite-datepicker/node_modules/flowbite": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/flowbite/-/flowbite-2.5.2.tgz", + "integrity": "sha512-kwFD3n8/YW4EG8GlY3Od9IoKND97kitO+/ejISHSqpn3vw2i5K/+ZI8Jm2V+KC4fGdnfi0XZ+TzYqQb4Q1LshA==", + "license": "MIT", + "dependencies": { + "@popperjs/core": "^2.9.3", + "flowbite-datepicker": "^1.3.0", + "mini-svg-data-uri": "^1.4.3" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "license": "MIT" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/laravel-vite-plugin": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.2.0.tgz", + "integrity": "sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "vite-plugin-full-reload": "^1.1.0" + }, + "bin": { + "clean-orphaned-assets": "bin/clean.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0" + } + }, + "node_modules/lightningcss": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "license": "MIT", + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.41.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz", + "integrity": "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.7" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.41.1", + "@rollup/rollup-android-arm64": "4.41.1", + "@rollup/rollup-darwin-arm64": "4.41.1", + "@rollup/rollup-darwin-x64": "4.41.1", + "@rollup/rollup-freebsd-arm64": "4.41.1", + "@rollup/rollup-freebsd-x64": "4.41.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.41.1", + "@rollup/rollup-linux-arm-musleabihf": "4.41.1", + "@rollup/rollup-linux-arm64-gnu": "4.41.1", + "@rollup/rollup-linux-arm64-musl": "4.41.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.41.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1", + "@rollup/rollup-linux-riscv64-gnu": "4.41.1", + "@rollup/rollup-linux-riscv64-musl": "4.41.1", + "@rollup/rollup-linux-s390x-gnu": "4.41.1", + "@rollup/rollup-linux-x64-gnu": "4.41.1", + "@rollup/rollup-linux-x64-musl": "4.41.1", + "@rollup/rollup-win32-arm64-msvc": "4.41.1", + "@rollup/rollup-win32-ia32-msvc": "4.41.1", + "@rollup/rollup-win32-x64-msvc": "4.41.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", + "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/tapable": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "devOptional": true, + "license": "0BSD" + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-plugin-full-reload": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.2.0.tgz", + "integrity": "sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "picomatch": "^2.3.1" + } + }, + "node_modules/vite-plugin-full-reload/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/yaml": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", + "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", + "devOptional": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..cb977ec --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "private": true, + "type": "module", + "scripts": { + "build": "vite build", + "dev": "vite" + }, + "devDependencies": { + "autoprefixer": "^10.4.21", + "axios": "^1.7.4", + "concurrently": "^9.0.1", + "laravel-vite-plugin": "^1.2.0", + "postcss": "^8.5.3", + "tailwindcss": "^3.4.17", + "vite": "^6.0.11" + }, + "dependencies": { + "@heroicons/react": "^2.2.0", + "@tailwindcss/vite": "^4.1.3", + "flowbite": "^3.1.2" + } +} diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..506b9a3 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,33 @@ + + + + + tests/Unit + + + tests/Feature + + + + + app + + + + + + + + + + + + + + + + diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..49c0612 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/public/.DS_Store b/public/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5f4171967e93a414942a9c15bcd491ee00e2f69a GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8Nhm@N3OxqA7Hn$|7B3;z7cim+m70*C!8BW%)E-J9XMG``#OHBl zcLSE@;7P>Jz~-BspWU4gvOkP5?k%D|V>V;VgoembsSz~Sx*9qdk;^es7O;ZF;WD4q z4D=UGxONlQ%%*I{zO6q@MF_r+aF!-{(d&KkMzgiIZy1)*HXi(EvGj|eSma(Xzr)_O z5NTNHL3oqI%ZYt>A+jP!vUn~Nk|>6d``aXo#L^RsEXrlBuN;lOFx$IRGF3_p5CcDC0QUz68ltPQR4BI&_~7*!{VhZk(D5yS=xB5`mI}cG z!c{7uO6B^A!Bslg9UbRtEETGB#^uZ~j-I)Cyl^=?*c}j~E~Z{uu+jHTK6I6s6DBt@7}!b)Y>$L&3Nb6%f!jE& + + Options -MultiViews -Indexes + + + RewriteEngine On + + # Handle Authorization Header + RewriteCond %{HTTP:Authorization} . + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + + # Handle X-XSRF-Token Header + RewriteCond %{HTTP:x-xsrf-token} . + RewriteRule .* - [E=HTTP_X_XSRF_TOKEN:%{HTTP:X-XSRF-Token}] + + # Redirect Trailing Slashes If Not A Folder... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_URI} (.+)/$ + RewriteRule ^ %1 [L,R=301] + + # Send Requests To Front Controller... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..e69de29 diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..947d989 --- /dev/null +++ b/public/index.php @@ -0,0 +1,17 @@ +handleRequest(Request::capture()); diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..eb05362 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/public/template/css/main.css b/public/template/css/main.css new file mode 100644 index 0000000..9cb4bb8 --- /dev/null +++ b/public/template/css/main.css @@ -0,0 +1,1730 @@ +*, +::after, +::before { + box-sizing: border-box; + border-width: 0; + border-style: solid; + border-color: #e5e7eb; +} + +::after, +::before { + --tw-content: ""; +} + +html { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, + "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", + "Noto Color Emoji"; +} + +body { + margin: 0; + line-height: inherit; +} + +hr { + height: 0; + color: inherit; + border-top-width: 1px; +} + +abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +a { + color: inherit; + text-decoration: inherit; +} + +b, +strong { + font-weight: bolder; +} + +code, +kbd, +pre, +samp { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, + "Liberation Mono", "Courier New", monospace; + font-size: 1em; +} + +small { + font-size: 80%; +} + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +table { + text-indent: 0; + border-color: inherit; + border-collapse: collapse; +} + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + font-size: 100%; + line-height: inherit; + color: inherit; + margin: 0; + padding: 0; +} + +button, +select { + text-transform: none; +} + +[type="button"], +[type="reset"], +[type="submit"], +button { + -webkit-appearance: button; + background-color: transparent; + background-image: none; +} + +:-moz-focusring { + outline: auto; +} + +:-moz-ui-invalid { + box-shadow: none; +} + +progress { + vertical-align: baseline; +} + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +[type="search"] { + -webkit-appearance: textfield; + outline-offset: -2px; +} + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; +} + +summary { + display: list-item; +} + +blockquote, +dd, +dl, +figure, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +menu, +ol, +ul { + list-style: none; + margin: 0; + padding: 0; +} + +textarea { + resize: vertical; +} + +input::-moz-placeholder, +textarea::-moz-placeholder { + opacity: 1; + color: #9ca3af; +} + +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { + opacity: 1; + color: #9ca3af; +} + +input::placeholder, +textarea::placeholder { + opacity: 1; + color: #9ca3af; +} + +[role="button"], +button { + cursor: pointer; +} + +:disabled { + cursor: default; +} + +audio, +canvas, +embed, +iframe, +img, +object, +svg, +video { + display: block; + vertical-align: middle; +} + +img, +video { + max-width: 100%; + height: auto; +} + +[hidden] { + display: none; +} + +*, +::after, +::before { + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-scroll-snap-strictness: proximity; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; +} + +@media (min-width: 1024px) { + .navbar, + .navbar-end, + .navbar-menu, + .navbar-start { + display: flex; + align-items: stretch; + } +} + +.navbar { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 30; + display: flex; + height: 3.5rem; + width: 100vw; + border-bottom-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +@media (min-width: 1024px) { + .navbar { + width: auto; + padding-left: 15rem; + } +} + +.navbar-brand { + display: flex; + height: 3.5rem; + flex: 1 1 0%; + align-items: stretch; +} + +.navbar-brand.is-right { + flex: none; +} + +@media (min-width: 1024px) { + .navbar-brand.is-right { + display: none; + } +} + +.navbar-brand .navbar-item { + display: flex; + align-items: center; +} + +.navbar-item, +.navbar-link { + display: block; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.navbar-item { + position: relative; + flex-shrink: 0; + flex-grow: 0; +} + +@media (min-width: 1024px) { + .navbar-item { + display: flex; + align-items: center; + } + + .navbar-item.mobile-aside-button { + display: none; + } + + .navbar-item.has-divider { + border-right-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); + } +} + +.navbar-item > .navbar-link { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + +@media (min-width: 1024px) { + .navbar-item > .navbar-link { + background-color: transparent; + } +} + +.navbar-item .icon + span { + margin-left: 0.5rem; +} + +.navbar-item.has-user-avatar > .navbar-link { + display: flex; + align-items: center; +} + +.navbar-item.has-user-avatar .user-avatar { + margin-right: 0.75rem; + display: inline-flex; + height: 1.5rem; + width: 1.5rem; +} + +.navbar-item.dropdown { + padding: 0; +} + +@media (min-width: 1024px) { + .navbar-item.dropdown { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + } +} + +.navbar-item.dropdown > .navbar-link .icon:last-child { + display: none; +} + +@media (min-width: 1024px) { + .navbar-item.dropdown > .navbar-link .icon:last-child { + display: inline-flex; + } + + .navbar-item.desktop-icon-only { + width: 4rem; + justify-content: center; + } + + .navbar-item.desktop-icon-only span:last-child { + display: none; + } +} + +.navbar-item .input { + border-width: 0; +} + +.navbar-menu { + max-height: calc(100vh - 3.5rem); + position: absolute; + top: 3.5rem; + left: 0; + display: none; + width: 100vw; + overflow: auto; + border-bottom-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); + --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), + 0 1px 2px -1px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), + var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +@media (min-width: 1024px) { + .navbar-menu { + position: static; + display: flex; + flex-grow: 1; + overflow: visible; + border-bottom-width: 0; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), + var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + } +} + +.navbar-menu.active { + display: block; +} + +@media (min-width: 1024px) { + .navbar-end { + margin-left: auto; + justify-content: flex-end; + } +} + +.navbar-item .navbar-dropdown { + font-size: 0.875rem; + line-height: 1.25rem; +} + +@media (min-width: 1024px) { + .navbar-item .navbar-dropdown { + position: absolute; + top: 100%; + left: 0; + z-index: 20; + min-width: 100%; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-top-width: 2px; + --tw-border-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); + --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), + 0 2px 4px -2px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), + 0 2px 4px -2px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), + var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); + } + + .navbar-item:not(.active) .navbar-dropdown { + display: none; + } +} + +.navbar-item.active.dropdown > .navbar-link, +.navbar-item.active:not(.dropdown) { + --tw-text-opacity: 1; + color: rgb(59 130 246 / var(--tw-text-opacity)); +} + +.field:not(:last-child) { + margin-bottom: 0.75rem; +} + +.field.spaced:not(:last-child) { + margin-bottom: 1.5rem; +} + +.field-body .field .field { + margin-bottom: 0; +} + +.field.addons { + display: flex; + justify-content: flex-start; +} + +.field.addons .control.expanded { + flex-shrink: 1; + flex-grow: 1; +} + +.field.addons .control:first-child:not(:only-child) .input, +.field.addons .control:first-child:not(:only-child) .select select { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + border-right-width: 0; +} + +.field.addons .control:last-child:not(:only-child) .input, +.field.addons .control:last-child:not(:only-child) .select select { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-left-width: 0; +} + +.field.grouped { + display: flex; + justify-content: flex-start; +} + +.field.grouped > .control:not(:last-child) { + margin-right: 0.75rem; +} + +.field.grouped.multiline { + flex-wrap: wrap; +} + +.label { + margin-bottom: 0.5rem; + display: block; + font-weight: 700; +} + +.control { + position: relative; +} + +.control.icons-left, +.control.icons-right { + position: relative; +} + +.file-cta, +.file-name, +.input, +.select select, +.textarea { + border-radius: 0.25rem; + border-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(156 163 175 / var(--tw-border-opacity)); + padding-left: 0.75rem; + padding-right: 0.75rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.file-cta, +.file-name, +.input, +.select select { + height: 2.5rem; +} + +.input, +.select select, +.textarea { + width: 100%; + max-width: 100%; + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} + +.input:focus, +.select select:focus, +.textarea:focus { + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); + outline: 2px solid transparent; + outline-offset: 2px; + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 + var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 + calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), + var(--tw-shadow, 0 0 #0000); +} + +.input[readonly] { + pointer-events: none; + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + +.textarea { + height: 6rem; +} + +.control.icons-left .icon, +.control.icons-right .icon { + position: absolute; + top: 0; + z-index: 10; + height: 2.5rem; + width: 2.5rem; +} + +.control.icons-left .input, +.control.icons-left .select select { + padding-left: 2.5rem; +} + +.control.icons-left .icon.left { + left: 0; +} + +.control.icons-right .input, +.control.icons-right .select select { + padding-right: 2.5rem; +} + +.control.icons-right .icon.right { + right: 0; +} + +.help { + margin-top: 0.25rem; + display: block; + font-size: 0.75rem; + line-height: 1rem; + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +.file { + position: relative; + display: flex; + align-items: stretch; + justify-content: flex-start; +} + +.upload { + display: inline-flex; +} + +.upload input[type="file"] { + position: absolute; + top: 0; + left: 0; + z-index: -1; + height: 100%; + width: 100%; + cursor: pointer; + opacity: 0; + outline: 2px solid transparent; + outline-offset: 2px; +} + +.mx-auto { + margin-left: auto; + margin-right: auto; +} + +.mb-6 { + margin-bottom: 1.5rem; +} + +.block { + display: block; +} + +.flex { + display: flex; +} + +.table { + display: table; +} + +.grid { + display: grid; +} + +.hidden { + display: none; +} + +.h-full { + height: 100%; +} + +.h-48 { + height: 12rem; +} + +.h-8 { + height: 2rem; +} + +.w-48 { + width: 12rem; +} + +.w-auto { + width: auto; +} + +.grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); +} + +.flex-col { + flex-direction: column; +} + +.items-center { + align-items: center; +} + +.justify-start { + justify-content: flex-start; +} + +.justify-between { + justify-content: space-between; +} + +.gap-6 { + gap: 1.5rem; +} + +.space-y-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); +} + +.space-x-3 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.75rem * var(--tw-space-x-reverse)); + margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse))); +} + +.space-y-6 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); +} + +.rounded-full { + border-radius: 9999px; +} + +.font-black { + font-weight: 900; +} + +.text-green-500 { + --tw-text-opacity: 1; + color: rgb(34 197 94 / var(--tw-text-opacity)); +} + +.text-blue-500 { + --tw-text-opacity: 1; + color: rgb(59 130 246 / var(--tw-text-opacity)); +} + +.text-red-500 { + --tw-text-opacity: 1; + color: rgb(239 68 68 / var(--tw-text-opacity)); +} + +.text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +body { + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity)); + padding-top: 3.5rem; + font-size: 1rem; + line-height: 1.5rem; +} + +@media (min-width: 1024px) { + body { + padding-left: 15rem; + } +} + +#app { + width: 100vw; + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +@media (min-width: 1024px) { + #app { + width: auto; + } +} + +.main-section { + padding: 1.5rem; +} + +.dropdown { + cursor: pointer; +} + +.clipped, +.clipped body { + overflow: hidden; +} + +.m-clipped, +.m-clipped body { + overflow: hidden; +} + +@media (min-width: 1024px) { + .m-clipped, + .m-clipped body { + overflow: visible; + } +} + +.form-screen body { + padding: 0; +} + +.form-screen .main-section { + display: flex; + height: 100vh; + align-items: center; + justify-content: center; +} + +.aside { + position: fixed; + left: -15rem; + top: 0; + z-index: 40; + height: 100vh; + width: 15rem; + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); + transition-property: all; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +@media (min-width: 1024px) { + .aside { + left: 0; + } +} + +.aside-tools { + display: flex; + height: 3.5rem; + width: 100%; + flex: 1 1 0%; + flex-direction: row; + align-items: center; + --tw-bg-opacity: 1; + background-color: rgb(17 24 39 / var(--tw-bg-opacity)); + padding-left: 0.75rem; + padding-right: 0.75rem; + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.aside-mobile-expanded .aside { + left: 0; +} + +.aside-mobile-expanded .navbar { + margin-left: 15rem; +} + +.aside-mobile-expanded #app { + margin-left: 15rem; +} + +.aside-mobile-expanded, +.aside-mobile-expanded body { + overflow: hidden; +} + +@media (min-width: 1024px) { + .aside-mobile-expanded, + .aside-mobile-expanded body { + overflow: visible; + } +} + +.menu-label { + padding: 0.75rem; + font-size: 0.75rem; + line-height: 1rem; + text-transform: uppercase; + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} + +.menu-list li a { + display: flex; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + --tw-text-opacity: 1; + color: rgb(209 213 219 / var(--tw-text-opacity)); +} + +.menu-list li > a:hover { + --tw-bg-opacity: 1; + background-color: rgb(55 65 81 / var(--tw-bg-opacity)); +} + +.menu-list li a .menu-item-label { + flex-grow: 1; +} + +.menu-list li a .icon { + width: 3rem; + flex: none; +} + +.menu-list li.active > a { + --tw-bg-opacity: 1; + background-color: rgb(55 65 81 / var(--tw-bg-opacity)); +} + +.menu-list li ul { + display: none; +} + +.menu-list li ul a { + padding: 0.75rem; + font-size: 0.875rem; + line-height: 1.25rem; +} + +.menu-list li.active ul { + display: block; + --tw-bg-opacity: 1; + background-color: rgb(75 85 99 / var(--tw-bg-opacity)); +} + +.is-title-bar { + border-bottom-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); + padding: 1.5rem; +} + +.is-title-bar li { + display: inline-block; + padding-right: 0.75rem; + font-size: 1.5rem; + line-height: 2rem; + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +.is-title-bar li:not(:last-child):after { + content: "/"; + display: inline-block; + padding-left: 0.75rem; +} + +.is-title-bar li:last-child { + padding-right: 0; + font-weight: 900; + --tw-text-opacity: 1; + color: rgb(0 0 0 / var(--tw-text-opacity)); +} + +.button { + display: inline-flex; + cursor: pointer; + justify-content: center; + white-space: nowrap; + border-radius: 0.25rem; + border-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(249 250 251 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); + padding-left: 1rem; + padding-right: 1rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + text-align: center; + --tw-text-opacity: 1; + color: rgb(0 0 0 / var(--tw-text-opacity)); +} + +.button:hover { + --tw-border-opacity: 1; + border-color: rgb(107 114 128 / var(--tw-border-opacity)); +} + +.button:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.button.addon-right { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.button.addon-left { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.button.small { + padding: 0.25rem; + font-size: 0.75rem; + line-height: 1rem; +} + +.button.small.textual { + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.button.active { + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); +} + +.button.active:hover { + --tw-border-opacity: 1; + border-color: rgb(107 114 128 / var(--tw-border-opacity)); +} + +.button.green { + --tw-border-opacity: 1; + border-color: rgb(34 197 94 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(34 197 94 / var(--tw-bg-opacity)); + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.button.green:hover { + --tw-bg-opacity: 1; + background-color: rgb(22 163 74 / var(--tw-bg-opacity)); +} + +.button.red { + --tw-border-opacity: 1; + border-color: rgb(239 68 68 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(239 68 68 / var(--tw-bg-opacity)); + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.button.red:hover { + --tw-bg-opacity: 1; + background-color: rgb(220 38 38 / var(--tw-bg-opacity)); +} + +.button.blue { + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.button.blue:hover { + --tw-bg-opacity: 1; + background-color: rgb(37 99 235 / var(--tw-bg-opacity)); +} + +.button.light { + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + +.button.light:hover { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} + +.buttons { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: flex-start; +} + +.buttons.nowrap { + flex-wrap: nowrap; +} + +.buttons.right { + justify-content: flex-end; +} + +.buttons .button { + margin-left: 0.25rem; + margin-right: 0.25rem; +} + +.is-hero-bar { + border-bottom-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); + padding: 1.5rem; +} + +.is-hero-bar h1 { + font-size: 1.875rem; + line-height: 2.25rem; + font-weight: 600; + line-height: 1.25; +} + +.card { + border-radius: 0.25rem; + border-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} + +.card.has-table .card-content { + padding: 0; +} + +.card-content { + padding: 1.5rem; +} + +.card-content hr { + margin-top: 1.5rem; + margin-bottom: 1.5rem; + margin-left: -1.5rem; + margin-right: -1.5rem; +} + +.card.empty .card-content { + padding-top: 3rem; + padding-bottom: 3rem; + text-align: center; + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +.card-header { + display: flex; + align-items: stretch; + border-bottom-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); +} + +.card-header-icon, +.card-header-title { + display: flex; + align-items: center; + padding-top: 0.75rem; + padding-bottom: 0.75rem; + padding-left: 1rem; + padding-right: 1rem; +} + +.card-header-title { + flex-grow: 1; + font-weight: 700; +} + +.card-header-icon { + justify-content: center; +} + +.widget-label h3 { + font-size: 1.125rem; + line-height: 1.75rem; + line-height: 1.25; + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +.widget-label h1 { + font-size: 1.875rem; + line-height: 2.25rem; + font-weight: 600; + line-height: 1.25; +} + +.form-screen .card { + width: 91.666667%; + border-radius: 0.5rem; + --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25); + --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), + var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +@media (min-width: 1024px) { + .form-screen .card { + width: 41.666667%; + } +} + +.icon { + display: inline-flex; + height: 1.5rem; + width: 1.5rem; + align-items: center; + justify-content: center; +} + +.icon.widget-icon { + height: 5rem; + width: 5rem; +} + +.icon.large { + height: 3rem; + width: 3rem; +} + +.icon i { + display: inline-flex; +} + +table { + width: 100%; +} + +thead { + display: none; +} + +@media (min-width: 1024px) { + thead { + display: table-header-group; + } +} + +tr { + position: relative; + display: block; + max-width: 100%; + border-bottom-width: 4px; + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); +} + +@media (min-width: 1024px) { + tr { + display: table-row; + border-bottom-width: 0; + } +} + +tr:last-child { + border-bottom-width: 0; +} + +@media (min-width: 1024px) { + th { + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + text-align: left; + } +} + +td { + display: flex; + justify-content: space-between; + border-bottom-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); + padding-top: 0.75rem; + padding-bottom: 0.75rem; + padding-left: 1rem; + padding-right: 1rem; + text-align: right; + vertical-align: top; +} + +@media (min-width: 1024px) { + td { + display: table-cell; + border-bottom-width: 0; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + text-align: left; + vertical-align: middle; + } + + tr:nth-child(odd) td { + --tw-bg-opacity: 1; + background-color: rgb(249 250 251 / var(--tw-bg-opacity)); + } +} + +td:last-child { + border-bottom-width: 0; +} + +@media (min-width: 1024px) { + tbody tr:hover td { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); + } +} + +td:before { + content: attr(data-label); + padding-right: 0.75rem; + text-align: left; + font-weight: 600; +} + +@media (min-width: 1024px) { + td:before { + display: none; + } + + td.checkbox-cell, + th.checkbox-cell { + width: 1.25rem; + } +} + +td.progress-cell progress { + display: flex; + width: 40%; + align-self: center; +} + +@media (min-width: 1024px) { + td.progress-cell progress { + width: 100%; + } +} + +td.image-cell { + border-bottom-width: 0; +} + +@media (min-width: 1024px) { + td.image-cell { + width: 1.5rem; + } +} + +td.actions-cell:before, +td.image-cell:before { + display: none; +} + +td.image-cell .image { + margin-left: auto; + margin-right: auto; + height: 6rem; + width: 6rem; +} + +@media (min-width: 1024px) { + td.image-cell .image { + height: 1.5rem; + width: 1.5rem; + } +} + +.table-pagination { + border-top-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(243 244 246 / var(--tw-border-opacity)); + padding-left: 1.5rem; + padding-right: 1.5rem; + padding-top: 0.75rem; + padding-bottom: 0.75rem; +} + +progress { + height: 0.75rem; + overflow: hidden; + border-radius: 9999px; +} + +progress::-webkit-progress-bar { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} + +progress::-webkit-progress-value { + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); +} + +progress::-moz-progress-bar { + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); +} + +progress::-ms-fill { + border-width: 0; + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); +} + +.image { + position: relative; + display: block; +} + +.image img { + display: block; + height: auto; + width: 100%; + max-width: 100%; +} + +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 40; + display: none; + flex-direction: column; + align-items: center; + justify-content: center; + overflow: hidden; +} + +.modal.active { + display: flex; +} + +.modal-background { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: rgb(17 24 39 / var(--tw-bg-opacity)); + --tw-bg-opacity: 0.8; +} + +.modal-card { + max-height: calc(100vh - 160px); + position: relative; + display: flex; + width: 100%; + flex-direction: column; + overflow: hidden; +} + +@media (min-width: 1024px) { + .modal-card { + margin-left: auto; + margin-right: auto; + width: 40%; + } +} + +.modal-card-body { + flex-shrink: 1; + flex-grow: 1; +} + +.modal-card-body > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); +} + +.modal-card-body { + overflow: auto; + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); + padding: 1.5rem; +} + +.modal-card-foot, +.modal-card-head { + position: relative; + display: flex; + flex-shrink: 0; + align-items: center; + justify-content: flex-start; + --tw-border-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); + padding-left: 1.5rem; + padding-right: 1.5rem; + padding-top: 1rem; + padding-bottom: 1rem; +} + +.modal-card-head { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; + border-bottom-width: 1px; +} + +.modal-card-foot { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + border-top-width: 1px; +} + +.modal-card-foot .button:not(:last-child) { + margin-right: 0.5rem; +} + +.notification { + border-radius: 0.25rem; + padding-left: 0.75rem; + padding-right: 0.75rem; + padding-top: 1.5rem; + padding-bottom: 1.5rem; +} + +.notification:not(:last-child) { + margin-bottom: 1.5rem; +} + +.notification.blue { + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.notification.green { + --tw-bg-opacity: 1; + background-color: rgb(34 197 94 / var(--tw-bg-opacity)); + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.notification.red { + --tw-bg-opacity: 1; + background-color: rgb(239 68 68 / var(--tw-bg-opacity)); + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); +} + +.checkbox, +.radio, +.switch { + position: relative; + display: inline-flex; + cursor: pointer; + align-items: center; +} + +.checkbox input[type="checkbox"], +.radio input[type="radio"], +.switch input[type="checkbox"] { + position: absolute; + left: 0; + z-index: -1; + opacity: 0; +} + +.checkbox input[type="checkbox"] + .check, +.radio input[type="radio"] + .check, +.switch input[type="checkbox"] + .check { + border-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); +} + +.checkbox input[type="checkbox"] + .check:hover, +.radio input[type="radio"] + .check:hover, +.switch input[type="checkbox"] + .check:hover { + --tw-border-opacity: 1; + border-color: rgb(156 163 175 / var(--tw-border-opacity)); +} + +.checkbox input[type="checkbox"] + .check, +.radio input[type="radio"] + .check { + display: block; + height: 1.25rem; + width: 1.25rem; +} + +.checkbox input[type="checkbox"] + .check { + border-radius: 0.25rem; +} + +.switch input[type="checkbox"] + .check { + display: flex; + height: 1.5rem; + width: 3rem; + flex-shrink: 0; + align-items: center; + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); + padding: 0.125rem; +} + +.radio input[type="radio"] + .check, +.switch input[type="checkbox"] + .check, +.switch input[type="checkbox"] + .check:before { + border-radius: 9999px; +} + +.checkbox input[type="checkbox"]:checked + .check, +.radio input[type="radio"]:checked + .check { + border-width: 4px; + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); + background-position: center; + background-repeat: no-repeat; +} + +.checkbox input[type="checkbox"]:checked + .check { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1'%3E%3Cpath style='fill:%23fff' d='M 0.04038059,0.6267767 0.14644661,0.52071068 0.42928932,0.80355339 0.3232233,0.90961941 z M 0.21715729,0.80355339 0.85355339,0.16715729 0.95961941,0.2732233 0.3232233,0.90961941 z'%3E%3C/path%3E%3C/svg%3E"); +} + +.radio input[type="radio"]:checked + .check { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z' /%3E%3C/svg%3E"); +} + +.switch input[type="checkbox"]:checked + .check { + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(59 130 246 / var(--tw-bg-opacity)); +} + +.switch input[type="checkbox"] + .check:before { + content: ""; + display: block; + height: 1.25rem; + width: 1.25rem; + border-width: 1px; + --tw-border-opacity: 1; + border-color: rgb(209 213 219 / var(--tw-border-opacity)); + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} + +.switch input[type="checkbox"]:checked + .check:before { + transform: translate3d(110%, 0, 0); + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); +} + +.checkbox .control-label, +.radio .control-label, +.switch .control-label { + padding-left: 0.5rem; +} + +footer { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1.5rem; + padding-right: 1.5rem; +} + +@media (min-width: 768px) { + .md\:grid-cols-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .md\:flex-row { + flex-direction: row; + } + + .md\:space-y-0 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0px * var(--tw-space-y-reverse)); + } +} + +@media (min-width: 1024px) { + .lg\:grid-cols-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} diff --git a/public/template/img/justboil-logo.svg b/public/template/img/justboil-logo.svg new file mode 100644 index 0000000..8f7bf62 --- /dev/null +++ b/public/template/img/justboil-logo.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/template/img/logo.png b/public/template/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f720e9b9eb3bf53c179318e275a7203ee4d72c02 GIT binary patch literal 1271628 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