Compare commits

..
10 Commits
Author SHA1 Message Date
novysan87 d84dc81502 fix(students): default urut A-Z (full_name asc) di Data Siswa 2026-08-07 09:28:20 +07:00
novysan87 f075449018 fix(classes): halaman Kelas default TA berjalan (36 kelas) + filter pilih tahun ajaran 2026-08-07 08:49:44 +07:00
novysan87 830405a747 fix(classes): urutkan daftar kelas dari X ke XII (FIELD level, lalu nama) 2026-08-07 08:48:11 +07:00
novysan87 6614e8dfba feat(api): sync students kini mengirim photo_url dari dokumen PAS FOTO 2026-08-07 08:27:44 +07:00
novysan87 f772b5b354 feat: halaman publik — layanan dokumen kelulusan kini menampilkan 5 jenis dokumen sesuai database (SKL, Ijazah, Transkrip, Sertifikat UKK, Sertifikat LSP), bukan hanya SKL+Ijazah 2026-08-06 23:26:28 +07:00
novysan87 5170e9a1f2 revert: kembalikan halaman detail siswa seperti semula (Kangmas minta) 2026-08-06 23:23:05 +07:00
novysan87 e450d4c699 ui(premium): detail siswa — hero profil gradien (avatar inisial, NISN/NIS, chip kelas-jurusan-TA, status, aksi), 4 kartu KPI, kartu progres dokumen premium, timeline histori akademik, header kartu info gradien 2026-08-06 23:20:46 +07:00
novysan87 da614b063a fix: dropdown kelas ganda — scope forActiveAcademicYear (hanya TA aktif), ikuti filter TA di index; berlaku juga untuk form siswa, import, keluar, mutasi, prestasi, self-service 2026-08-06 23:18:03 +07:00
Sari 616d88ed4c fix: daftar siswa keluar diurutkan berdasarkan tanggal masuk terbaru (entry_date desc) 2026-08-03 11:47:55 +07:00
novysan87 520c6d3e48 fix: StudentController, AdminUserSeeder updates 2026-07-25 12:19:13 +07:00
15 changed files with 319 additions and 304 deletions
View File
@@ -27,6 +27,8 @@ class StudentSyncController extends Controller
'academicYear:id,name,start_year,end_year,is_active',
'department:id,code,name,description,is_active',
'classRoom:id,academic_year_id,department_id,name,level,is_active',
'parents:id,student_id,relation_type,name,nik,phone_number,is_alive',
'documents.documentType',
])
->orderBy('full_name')
->get([
@@ -52,6 +54,19 @@ class StudentSyncController extends Controller
'updated_at',
])
->map(function (Student $student) {
$photoDocument = $student->documents
->filter(function ($document) {
$code = strtoupper((string) ($document->documentType?->code ?? ''));
$name = strtolower((string) ($document->documentType?->name ?? ''));
return $code === 'PAS_FOTO'
|| $code === 'PAS FOTO'
|| str_contains($name, 'pas foto')
|| str_contains($name, 'pasfoto');
})
->sortByDesc('created_at')
->first();
return [
'id' => $student->id,
'student_number' => $student->student_number,
@@ -98,7 +113,19 @@ class StudentSyncController extends Controller
'phone_number' => $student->phone_number,
'email' => $student->email,
'photo_path' => $student->photo_path,
'photo_url' => $photoDocument?->file_path ? asset('storage/' . $photoDocument->file_path) : null,
'notes' => $student->notes,
'parents' => $student->parents
->where('is_alive', true)
->values()
->map(fn ($p) => [
'id' => $p->id,
'relation' => $p->relation_type,
'name' => $p->name,
'nik' => $p->nik,
'phone_number' => $p->phone_number,
])
->all(),
'updated_at' => $student->updated_at?->toISOString(),
];
})
@@ -23,21 +23,24 @@ class SchoolClassController extends Controller
public function index(Request $request): View
{
$search = trim((string) $request->get('search'));
$academicYearId = $request->integer('academic_year_id') ?: null;
$classes = SchoolClass::with(['academicYear', 'department'])
->withCount(['students', 'academicHistories'])
->when($academicYearId, fn ($query) => $query->where('academic_year_id', $academicYearId), fn ($query) => $query->forActiveAcademicYear())
->when($search !== '', function ($query) use ($search) {
$query->where('name', 'like', "%{$search}%")
->orWhere('level', 'like', "%{$search}%")
->orWhere('homeroom_teacher', 'like', "%{$search}%");
})
->latest()
->orderByRaw("FIELD(level, 'X', 'XI', 'XII'), name")
->paginate(10)
->withQueryString();
return view('classes.index', [
'classes' => $classes,
'search' => $search,
'academicYearId' => $academicYearId,
'academicYears' => AcademicYear::orderByDesc('start_year')->orderByDesc('end_year')->get(),
'importPreview' => $request->session()->get('class_import_preview'),
'importReferenceData' => $this->importReferenceData(),
@@ -82,7 +82,7 @@ class StudentAchievementController extends Controller
'category' => $category,
],
'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::forActiveAcademicYear()->orderBy('name')->pluck('name', 'id'),
'categoryOptions' => $categoryOptions,
'levelOptions' => $this->levelOptions(),
'summary' => [
+16 -92
View File
@@ -43,9 +43,9 @@ class StudentController extends Controller
$viewConfig = $this->resolveStudentViewConfig($viewMode, null);
$status = $viewConfig['status'];
$sort = (string) $request->get('sort', 'created_at');
$sort = (string) $request->get('sort', 'full_name');
$direction = strtolower((string) $request->get('direction', 'desc')) === 'asc' ? 'asc' : 'desc';
$direction = strtolower((string) $request->get('direction', $sort === 'full_name' ? 'asc' : 'desc')) === 'asc' ? 'asc' : 'desc';
$allowedSorts = [
'full_name' => 'students.full_name',
@@ -187,7 +187,11 @@ class StudentController extends Controller
],
'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'),
'departments' => Department::where('is_active', true)->orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::when(
$academicYearId,
fn ($query) => $query->where('academic_year_id', $academicYearId),
fn ($query) => $query->forActiveAcademicYear()
)->orderBy('name')->pluck('name', 'id'),
'statuses' => $viewConfig['view'] === 'all'
? [
'active' => 'Aktif',
@@ -506,9 +510,6 @@ class StudentController extends Controller
'Tanggal Lahir (YYYY-MM-DD)',
'Agama',
'Kewarganegaraan',
'No. Kartu Keluarga',
'Anak Ke',
'Jumlah Saudara',
'Nomor HP',
'Email',
'Alamat',
@@ -523,30 +524,6 @@ class StudentController extends Controller
'Tanggal Masuk (YYYY-MM-DD)',
'Status',
'Catatan',
'Nama Ayah',
'NIK Ayah',
'Tahun Lahir Ayah',
'Pendidikan Ayah',
'Pekerjaan Ayah',
'No. HP Ayah',
'Alamat Ayah',
'Status Hidup Ayah',
'Nama Ibu',
'NIK Ibu',
'Tahun Lahir Ibu',
'Pendidikan Ibu',
'Pekerjaan Ibu',
'No. HP Ibu',
'Alamat Ibu',
'Status Hidup Ibu',
'Nama Wali',
'NIK Wali',
'Tahun Lahir Wali',
'Pendidikan Wali',
'Pekerjaan Wali',
'No. HP Wali',
'Alamat Wali',
'Status Hidup Wali',
];
$sheet->fromArray($headers, null, 'A1');
@@ -560,9 +537,6 @@ class StudentController extends Controller
'2010-01-15',
'Islam',
'Indonesia',
'3512345678901235',
'1',
'2',
'081234567890',
'contoh@siswa.local',
'Jl. Contoh No. 1',
@@ -577,30 +551,6 @@ class StudentController extends Controller
'2026-07-15',
'active',
'Catatan opsional',
'Budi Santoso',
'3512345678901111',
'1980',
'SMA',
'Wiraswasta',
'081200000001',
'Jl. Ayah No. 1',
'Ya',
'Siti Aminah',
'3512345678902222',
'1982',
'SMA',
'Ibu Rumah Tangga',
'081200000002',
'Jl. Ibu No. 1',
'Ya',
'Ahmad Wali',
'3512345678903333',
'1975',
'S1',
'Pegawai Swasta',
'081200000003',
'Jl. Wali No. 1',
'Ya',
], null, 'A2');
for ($columnIndex = 1; $columnIndex <= count($headers); $columnIndex++) {
@@ -636,9 +586,6 @@ class StudentController extends Controller
['Tanggal Lahir (YYYY-MM-DD)', 'Format contoh: 2010-01-15.'],
['Agama', 'Opsional, contoh: Islam, Kristen, Katolik, Hindu, Buddha, Konghucu.'],
['Kewarganegaraan', 'Opsional, default aman: Indonesia.'],
['No. Kartu Keluarga', 'Opsional.'],
['Anak Ke', 'Opsional, angka bulat minimal 1.'],
['Jumlah Saudara', 'Opsional, angka bulat minimal 0.'],
['Nomor HP', 'Opsional.'],
['Email', 'Opsional, harus format email valid bila diisi.'],
['Alamat', 'Opsional.'],
@@ -652,31 +599,6 @@ class StudentController extends Controller
['Kelas', 'Isi dengan nama kelas persis seperti sheet Referensi.'],
['Tanggal Masuk (YYYY-MM-DD)', 'Format contoh: 2026-07-15.'],
['Status', 'Gunakan: active, inactive, transferred, graduated, dropped.'],
['Catatan', 'Opsional.'],
['Nama Ayah', 'Opsional.'],
['NIK Ayah', 'Opsional.'],
['Tahun Lahir Ayah', 'Opsional, angka 4 digit.'],
['Pendidikan Ayah', 'Opsional.'],
['Pekerjaan Ayah', 'Opsional.'],
['No. HP Ayah', 'Opsional.'],
['Alamat Ayah', 'Opsional.'],
['Status Hidup Ayah', 'Opsional, isi Ya/Tidak atau Hidup/Meninggal.'],
['Nama Ibu', 'Opsional.'],
['NIK Ibu', 'Opsional.'],
['Tahun Lahir Ibu', 'Opsional, angka 4 digit.'],
['Pendidikan Ibu', 'Opsional.'],
['Pekerjaan Ibu', 'Opsional.'],
['No. HP Ibu', 'Opsional.'],
['Alamat Ibu', 'Opsional.'],
['Status Hidup Ibu', 'Opsional, isi Ya/Tidak atau Hidup/Meninggal.'],
['Nama Wali', 'Opsional.'],
['NIK Wali', 'Opsional.'],
['Tahun Lahir Wali', 'Opsional, angka 4 digit.'],
['Pendidikan Wali', 'Opsional.'],
['Pekerjaan Wali', 'Opsional.'],
['No. HP Wali', 'Opsional.'],
['Alamat Wali', 'Opsional.'],
['Status Hidup Wali', 'Opsional, isi Ya/Tidak atau Hidup/Meninggal.'],
], null, 'A1');
foreach (range('A', 'B') as $column) {
$guideSheet->getColumnDimension($column)->setAutoSize(true);
@@ -699,7 +621,12 @@ class StudentController extends Controller
$path = storage_path('app/private/student-import-example.xlsx');
abort_unless(file_exists($path), 404, 'File contoh import siswa belum tersedia.');
if (! file_exists($path)) {
$response = $this->downloadImportTemplate();
$response->headers->set('Content-Disposition', 'attachment; filename="contoh-import-siswa.xlsx"');
return $response;
}
return response()->file($path, [
'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
@@ -783,11 +710,8 @@ class StudentController extends Controller
protected function formData(?Student $student = null): array
{
$classOptionsQuery = SchoolClass::query()
->when(
$student?->class_id,
fn ($query) => $query->where('is_active', true)->orWhere('id', $student->class_id),
fn ($query) => $query->where('is_active', true)
)
->forActiveAcademicYear()
->when($student?->class_id, fn ($query) => $query->orWhere('id', $student->class_id))
->orderBy('name');
return [
@@ -824,7 +748,7 @@ class StudentController extends Controller
{
$academicYears = AcademicYear::where('is_active', true)->orderBy('name')->pluck('name', 'id');
$departments = Department::where('is_active', true)->orderBy('name')->pluck('name', 'id');
$classes = SchoolClass::with(['academicYear', 'department'])->where('is_active', true)->orderBy('name')->get();
$classes = SchoolClass::with(['academicYear', 'department'])->forActiveAcademicYear()->where('is_active', true)->orderBy('name')->get();
return [
'academicYears' => $academicYears,
@@ -35,8 +35,8 @@ class StudentExitController extends Controller
->when($classId, fn ($query) => $query->where('class_id', $classId));
$studentExits = (clone $studentExitsQuery)
->latest('exit_date')
->latest('id')
->orderByDesc('entry_date')
->orderByDesc('id')
->paginate(10)
->withQueryString();
@@ -61,7 +61,7 @@ class StudentExitController extends Controller
],
'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'),
'departments' => Department::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::forActiveAcademicYear()->orderBy('name')->pluck('name', 'id'),
'summary' => [
'total' => $totalExits,
'with_letter' => $withLetterCount,
@@ -52,7 +52,7 @@ class StudentSelfServiceController extends Controller
'status' => $status,
],
'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::forActiveAcademicYear()->orderBy('name')->pluck('name', 'id'),
'statuses' => $statusLabels,
'summary' => [
'total' => (clone $summaryBaseQuery)->count(),
@@ -61,7 +61,7 @@ class StudentTransferController extends Controller
],
'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'),
'departments' => Department::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::orderBy('name')->pluck('name', 'id'),
'classes' => SchoolClass::forActiveAcademicYear()->orderBy('name')->pluck('name', 'id'),
'summary' => [
'total' => $totalTransfers,
'with_letter' => $withLetterCount,
+8
View File
@@ -36,6 +36,14 @@ class SchoolClass extends Model
return $this->belongsTo(AcademicYear::class);
}
/**
* Scope: hanya kelas pada tahun ajaran yang sedang aktif.
*/
public function scopeForActiveAcademicYear($query)
{
return $query->whereHas('academicYear', fn ($q) => $q->where('is_active', true));
}
public function department(): BelongsTo
{
return $this->belongsTo(Department::class);
+1
View File
@@ -17,6 +17,7 @@ class AdminUserSeeder extends Seeder
['email' => 'admin@kesiswaan.local'],
[
'name' => 'Administrator',
'role' => 'admin',
'password' => Hash::make('Admin123!'),
'email_verified_at' => now(),
]
+176 -175
View File
@@ -128,9 +128,9 @@
}
},
"node_modules/@napi-rs/wasm-runtime": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.3.tgz",
"integrity": "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==",
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
"integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -185,9 +185,9 @@
}
},
"node_modules/@oxc-project/types": {
"version": "0.124.0",
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.124.0.tgz",
"integrity": "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==",
"version": "0.126.0",
"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.126.0.tgz",
"integrity": "sha512-oGfVtjAgwQVVpfBrbtk4e1XDyWHRFta6BS3GWVzrF8xYBT2VGQAk39yJS/wFSMrZqoiCU4oghT3Ch0HaHGIHcQ==",
"dev": true,
"license": "MIT",
"funding": {
@@ -195,9 +195,9 @@
}
},
"node_modules/@rolldown/binding-android-arm64": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.15.tgz",
"integrity": "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.16.tgz",
"integrity": "sha512-rhY3k7Bsae9qQfOtph2Pm2jZEA+s8Gmjoz4hhmx70K9iMQ/ddeae+xhRQcM5IuVx5ry1+bGfkvMn7D6MJggVSA==",
"cpu": [
"arm64"
],
@@ -212,9 +212,9 @@
}
},
"node_modules/@rolldown/binding-darwin-arm64": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.15.tgz",
"integrity": "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.16.tgz",
"integrity": "sha512-rNz0yK078yrNn3DrdgN+PKiMOW8HfQ92jQiXxwX8yW899ayV00MLVdaCNeVBhG/TbH3ouYVObo8/yrkiectkcQ==",
"cpu": [
"arm64"
],
@@ -229,9 +229,9 @@
}
},
"node_modules/@rolldown/binding-darwin-x64": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.15.tgz",
"integrity": "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.16.tgz",
"integrity": "sha512-r/OmdR00HmD4i79Z//xO06uEPOq5hRXdhw7nzkxQxwSavs3PSHa1ijntdpOiZ2mzOQ3fVVu8C1M19FoNM+dMUQ==",
"cpu": [
"x64"
],
@@ -246,9 +246,9 @@
}
},
"node_modules/@rolldown/binding-freebsd-x64": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.15.tgz",
"integrity": "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.16.tgz",
"integrity": "sha512-KcRE5w8h0OnjUatG8pldyD14/CQ5Phs1oxfR+3pKDjboHRo9+MkqQaiIZlZRpsxC15paeXme/I127tUa9TXJ6g==",
"cpu": [
"x64"
],
@@ -263,9 +263,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.15.tgz",
"integrity": "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.16.tgz",
"integrity": "sha512-bT0guA1bpxEJ/ZhTRniQf7rNF8ybvXOuWbNIeLABaV5NGjx4EtOWBTSRGWFU9ZWVkPOZ+HNFP8RMcBokBiZ0Kg==",
"cpu": [
"arm"
],
@@ -280,9 +280,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-gnu": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.15.tgz",
"integrity": "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.16.tgz",
"integrity": "sha512-+tHktCHWV8BDQSjemUqm/Jl/TPk3QObCTIjmdDy/nlupcujZghmKK2962LYrqFpWu+ai01AN/REOH3NEpqvYQg==",
"cpu": [
"arm64"
],
@@ -297,9 +297,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-musl": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.15.tgz",
"integrity": "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.16.tgz",
"integrity": "sha512-3fPzdREH806oRLxpTWW1Gt4tQHs0TitZFOECB2xzCFLPKnSOy90gwA7P29cksYilFO6XVRY1kzga0cL2nRjKPg==",
"cpu": [
"arm64"
],
@@ -314,9 +314,9 @@
}
},
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.15.tgz",
"integrity": "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.16.tgz",
"integrity": "sha512-EKwI1tSrLs7YVw+JPJT/G2dJQ1jl9qlTTTEG0V2Ok/RdOenRfBw2PQdLPyjhIu58ocdBfP7vIRN/pvMsPxs/AQ==",
"cpu": [
"ppc64"
],
@@ -331,9 +331,9 @@
}
},
"node_modules/@rolldown/binding-linux-s390x-gnu": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.15.tgz",
"integrity": "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.16.tgz",
"integrity": "sha512-Uknladnb3Sxqu6SEcqBldQyJUpk8NleooZEc0MbRBJ4inEhRYWZX0NJu12vNf2mqAq7gsofAxHrGghiUYjhaLQ==",
"cpu": [
"s390x"
],
@@ -348,9 +348,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-gnu": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.15.tgz",
"integrity": "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.16.tgz",
"integrity": "sha512-FIb8+uG49sZBtLTn+zt1AJ20TqVcqWeSIyoVt0or7uAWesgKaHbiBh6OpA/k9v0LTt+PTrb1Lao133kP4uVxkg==",
"cpu": [
"x64"
],
@@ -365,9 +365,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-musl": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.15.tgz",
"integrity": "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.16.tgz",
"integrity": "sha512-RuERhF9/EgWxZEXYWCOaViUWHIboceK4/ivdtQ3R0T44NjLkIIlGIAVAuCddFxsZ7vnRHtNQUrt2vR2n2slB2w==",
"cpu": [
"x64"
],
@@ -382,9 +382,9 @@
}
},
"node_modules/@rolldown/binding-openharmony-arm64": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.15.tgz",
"integrity": "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.16.tgz",
"integrity": "sha512-mXcXnvd9GpazCxeUCCnZ2+YF7nut+ZOEbE4GtaiPtyY6AkhZWbK70y1KK3j+RDhjVq5+U8FySkKRb/+w0EeUwA==",
"cpu": [
"arm64"
],
@@ -399,9 +399,9 @@
}
},
"node_modules/@rolldown/binding-wasm32-wasi": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.15.tgz",
"integrity": "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.16.tgz",
"integrity": "sha512-3Q2KQxnC8IJOLqXmUMoYwyIPZU9hzRbnHaoV3Euz+VVnjZKcY8ktnNP8T9R4/GGQtb27C/UYKABxesKWb8lsvQ==",
"cpu": [
"wasm32"
],
@@ -411,16 +411,16 @@
"dependencies": {
"@emnapi/core": "1.9.2",
"@emnapi/runtime": "1.9.2",
"@napi-rs/wasm-runtime": "^1.1.3"
"@napi-rs/wasm-runtime": "^1.1.4"
},
"engines": {
"node": ">=14.0.0"
"node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@rolldown/binding-win32-arm64-msvc": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.15.tgz",
"integrity": "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.16.tgz",
"integrity": "sha512-tj7XRemQcOcFwv7qhpUxMTBbI5mWMlE4c1Omhg5+h8GuLXzyj8HviYgR+bB2DMDgRqUE+jiDleqSCRjx4aYk/Q==",
"cpu": [
"arm64"
],
@@ -435,9 +435,9 @@
}
},
"node_modules/@rolldown/binding-win32-x64-msvc": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.15.tgz",
"integrity": "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.16.tgz",
"integrity": "sha512-PH5DRZT+F4f2PTXRXR8uJxnBq2po/xFtddyabTJVJs/ZYVHqXPEgNIr35IHTEa6bpa0Q8Awg+ymkTaGnKITw4g==",
"cpu": [
"x64"
],
@@ -452,9 +452,9 @@
}
},
"node_modules/@rolldown/pluginutils": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.15.tgz",
"integrity": "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.16.tgz",
"integrity": "sha512-45+YtqxLYKDWQouLKCrpIZhke+nXxhsw+qAHVzHDVwttyBlHNBVs2K25rDXrZzhpTp9w1FlAlvweV1H++fdZoA==",
"dev": true,
"license": "MIT"
},
@@ -472,9 +472,9 @@
}
},
"node_modules/@tailwindcss/node": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.2.tgz",
"integrity": "sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.3.tgz",
"integrity": "sha512-dhXFXkW2dGvX4r/fi24gyXM0t1mFMrpykQjqrdA4SuavaMagm4SY1u5G2SCJwu1/0x/5RlZJ2VPjP3mKYQfCkA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -484,44 +484,44 @@
"lightningcss": "1.32.0",
"magic-string": "^0.30.21",
"source-map-js": "^1.2.1",
"tailwindcss": "4.2.2"
"tailwindcss": "4.2.3"
}
},
"node_modules/@tailwindcss/node/node_modules/tailwindcss": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.2.tgz",
"integrity": "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.3.tgz",
"integrity": "sha512-fA/NX5gMf0ooCLISgB0wScaWgaj6rjTN2SVAwleURjiya7ITNkV+VMmoHtKkldP6CIZoYCZyxb8zP/e2TWoEtQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@tailwindcss/oxide": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.2.tgz",
"integrity": "sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.3.tgz",
"integrity": "sha512-YyhwSBcxHLS3CU2Mk3dXDuVm8/Ia0+XvfpT8s9YQoICppkUeoobB3hgyGMYbyQ4vn6VgWH9bdv5UnzhTz2NPTQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 20"
},
"optionalDependencies": {
"@tailwindcss/oxide-android-arm64": "4.2.2",
"@tailwindcss/oxide-darwin-arm64": "4.2.2",
"@tailwindcss/oxide-darwin-x64": "4.2.2",
"@tailwindcss/oxide-freebsd-x64": "4.2.2",
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.2",
"@tailwindcss/oxide-linux-arm64-gnu": "4.2.2",
"@tailwindcss/oxide-linux-arm64-musl": "4.2.2",
"@tailwindcss/oxide-linux-x64-gnu": "4.2.2",
"@tailwindcss/oxide-linux-x64-musl": "4.2.2",
"@tailwindcss/oxide-wasm32-wasi": "4.2.2",
"@tailwindcss/oxide-win32-arm64-msvc": "4.2.2",
"@tailwindcss/oxide-win32-x64-msvc": "4.2.2"
"@tailwindcss/oxide-android-arm64": "4.2.3",
"@tailwindcss/oxide-darwin-arm64": "4.2.3",
"@tailwindcss/oxide-darwin-x64": "4.2.3",
"@tailwindcss/oxide-freebsd-x64": "4.2.3",
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.3",
"@tailwindcss/oxide-linux-arm64-gnu": "4.2.3",
"@tailwindcss/oxide-linux-arm64-musl": "4.2.3",
"@tailwindcss/oxide-linux-x64-gnu": "4.2.3",
"@tailwindcss/oxide-linux-x64-musl": "4.2.3",
"@tailwindcss/oxide-wasm32-wasi": "4.2.3",
"@tailwindcss/oxide-win32-arm64-msvc": "4.2.3",
"@tailwindcss/oxide-win32-x64-msvc": "4.2.3"
}
},
"node_modules/@tailwindcss/oxide-android-arm64": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.2.tgz",
"integrity": "sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.3.tgz",
"integrity": "sha512-0Jmt1U/zPqeKp1+fvgI3qMqrV5b/EcFIbE5Dl5KdPl5Ri6e+95nlYNjfB3w8hJBeASI4IQSnIMz0tdVP1AVO4g==",
"cpu": [
"arm64"
],
@@ -536,9 +536,9 @@
}
},
"node_modules/@tailwindcss/oxide-darwin-arm64": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.2.tgz",
"integrity": "sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.3.tgz",
"integrity": "sha512-c+/Etn/nghKBhd9fh2diG+3SEV1VTTPLlqH209yleofi28H87Cy6g1vsd3W3kf6r/dR5g4G4TEwHxo2Ydn6yFw==",
"cpu": [
"arm64"
],
@@ -553,9 +553,9 @@
}
},
"node_modules/@tailwindcss/oxide-darwin-x64": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.2.tgz",
"integrity": "sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.3.tgz",
"integrity": "sha512-1DrKKsdJTLuLWVdpaLZ0j/g9YbCZyP9xnwSqEvl3gY4ZHdXmX7TwVAHkoWUljOq7JK5zvzIGhrYmfE/2DJ5qaA==",
"cpu": [
"x64"
],
@@ -570,9 +570,9 @@
}
},
"node_modules/@tailwindcss/oxide-freebsd-x64": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.2.tgz",
"integrity": "sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.3.tgz",
"integrity": "sha512-HE6HHZYF8k7m80eVQ0RBvRGBdvvLvCpHiT38IRH9JSnBlt1T7gDzWoslWjmpXQFuqlRpzkCpbdKJa3NxWMfgVA==",
"cpu": [
"x64"
],
@@ -587,9 +587,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.2.tgz",
"integrity": "sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.3.tgz",
"integrity": "sha512-Li2wVd2kkKlKkTdpo7ujHSv6kxD1UYMvulAraikyvVf6AKNZ/VHbm8XoSNimZ+dF7SOFaDD2VAT64SK7WKcbjQ==",
"cpu": [
"arm"
],
@@ -604,9 +604,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.2.tgz",
"integrity": "sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.3.tgz",
"integrity": "sha512-otIiImZaHj9MiDK02ItoWxIVcMTZVAX2F1c32bg9y7ecV0AnN5JHDZqIO8LxWsTuig1d+Bjg0cBWn4A9sGJO9Q==",
"cpu": [
"arm64"
],
@@ -621,9 +621,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.2.tgz",
"integrity": "sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.3.tgz",
"integrity": "sha512-MmIA32rNEOrjh6wnevlR3OjjlCuwgZ4JMJo7Vrhk4Fk56Vxi7EeF7cekSKwvlrnfcn/ERC1LdcG3sFneU8WdoA==",
"cpu": [
"arm64"
],
@@ -638,9 +638,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.2.tgz",
"integrity": "sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.3.tgz",
"integrity": "sha512-BiCy1YV0IKO+xbD7gyZnENU4jdwDygeGQjncJoeIE5Kp4UqWHFsKUSJ3pp7vYURrqVzwJX2xD5gQeGnoXp4xPQ==",
"cpu": [
"x64"
],
@@ -655,9 +655,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.2.tgz",
"integrity": "sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.3.tgz",
"integrity": "sha512-venvyAu0AMKdr0c1Oz23IJJdZ72zSwKyHrLvqQV1cn49vPAJk3AuVtDkJ1ayk1sYI4M4j8Jv6ZGflpaP0QVSXQ==",
"cpu": [
"x64"
],
@@ -672,9 +672,9 @@
}
},
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.2.tgz",
"integrity": "sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.3.tgz",
"integrity": "sha512-e3kColrZZCdtbwIOc07cNQ2zNf1sTPXTYLjjPlsgsaf+ttzAg/hOlDyEgHoOlBGxM88nPxeVaOGe9ThqVzPncg==",
"bundleDependencies": [
"@napi-rs/wasm-runtime",
"@emnapi/core",
@@ -702,9 +702,9 @@
}
},
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.2.tgz",
"integrity": "sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.3.tgz",
"integrity": "sha512-qpwoUPzfu71cppxOtcz4LXMR1brljS13yOcAAnVHKIL++NJvSQKZBKlP39pVowd+G6Mq34YAbf4CUUYdLWL9gQ==",
"cpu": [
"arm64"
],
@@ -719,9 +719,9 @@
}
},
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.2.tgz",
"integrity": "sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.3.tgz",
"integrity": "sha512-dTRIlLRC5lCRHqO5DLb+A18HCvS394axmzqfnRNLptKVw7WuckpUwo1Z87Yw74mesbeIhnQTA2SZbRcIfVlwxg==",
"cpu": [
"x64"
],
@@ -736,24 +736,24 @@
}
},
"node_modules/@tailwindcss/vite": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.2.tgz",
"integrity": "sha512-mEiF5HO1QqCLXoNEfXVA1Tzo+cYsrqV7w9Juj2wdUFyW07JRenqMG225MvPwr3ZD9N1bFQj46X7r33iHxLUW0w==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.3.tgz",
"integrity": "sha512-pEvbC/NoOqxvqjy6IgelSakbzwin865CmOxJxmz3CSEbHJ2aF1B2183ALVasN0o6dOGhYfnVJOKKxVoyag+XeA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@tailwindcss/node": "4.2.2",
"@tailwindcss/oxide": "4.2.2",
"tailwindcss": "4.2.2"
"@tailwindcss/node": "4.2.3",
"@tailwindcss/oxide": "4.2.3",
"tailwindcss": "4.2.3"
},
"peerDependencies": {
"vite": "^5.2.0 || ^6 || ^7 || ^8"
}
},
"node_modules/@tailwindcss/vite/node_modules/tailwindcss": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.2.tgz",
"integrity": "sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.3.tgz",
"integrity": "sha512-fA/NX5gMf0ooCLISgB0wScaWgaj6rjTN2SVAwleURjiya7ITNkV+VMmoHtKkldP6CIZoYCZyxb8zP/e2TWoEtQ==",
"dev": true,
"license": "MIT"
},
@@ -857,9 +857,9 @@
"license": "MIT"
},
"node_modules/autoprefixer": {
"version": "10.4.27",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz",
"integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==",
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz",
"integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==",
"dev": true,
"funding": [
{
@@ -877,8 +877,8 @@
],
"license": "MIT",
"dependencies": {
"browserslist": "^4.28.1",
"caniuse-lite": "^1.0.30001774",
"browserslist": "^4.28.2",
"caniuse-lite": "^1.0.30001787",
"fraction.js": "^5.3.4",
"picocolors": "^1.1.1",
"postcss-value-parser": "^4.2.0"
@@ -906,9 +906,9 @@
}
},
"node_modules/baseline-browser-mapping": {
"version": "2.10.17",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.17.tgz",
"integrity": "sha512-HdrkN8eVG2CXxeifv/VdJ4A4RSra1DTW8dc/hdxzhGHN8QePs6gKaWM9pHPcpCoxYZJuOZ8drHmbdpLHjCYjLA==",
"version": "2.10.20",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.20.tgz",
"integrity": "sha512-1AaXxEPfXT+GvTBJFuy4yXVHWJBXa4OdbIebGN/wX5DlsIkU0+wzGnd2lOzokSk51d5LUmqjgBLRLlypLUqInQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -1003,9 +1003,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001787",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001787.tgz",
"integrity": "sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg==",
"version": "1.0.30001788",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001788.tgz",
"integrity": "sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==",
"dev": true,
"funding": [
{
@@ -1237,9 +1237,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.334",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.334.tgz",
"integrity": "sha512-mgjZAz7Jyx1SRCwEpy9wefDS7GvNPazLthHg8eQMJ76wBdGQQDW33TCrUTvQ4wzpmOrv2zrFoD3oNufMdyMpog==",
"version": "1.5.340",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.340.tgz",
"integrity": "sha512-908qahOGocRMinT2nM3ajCEM99H4iPdv84eagPP3FfZy/1ZGeOy2CZYzjhms81ckOPCXPlW7LkY4XpxD8r1DrA==",
"dev": true,
"license": "ISC"
},
@@ -1377,9 +1377,9 @@
}
},
"node_modules/follow-redirects": {
"version": "1.15.11",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
"integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
"dev": true,
"funding": [
{
@@ -1575,9 +1575,9 @@
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
"integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2164,9 +2164,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.9",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz",
"integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==",
"version": "8.5.10",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz",
"integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==",
"dev": true,
"funding": [
{
@@ -2391,12 +2391,13 @@
}
},
"node_modules/resolve": {
"version": "1.22.11",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
"integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
"version": "1.22.12",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
"integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"is-core-module": "^2.16.1",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
@@ -2423,14 +2424,14 @@
}
},
"node_modules/rolldown": {
"version": "1.0.0-rc.15",
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.15.tgz",
"integrity": "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==",
"version": "1.0.0-rc.16",
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.16.tgz",
"integrity": "sha512-rzi5WqKzEZw3SooTt7cgm4eqIoujPIyGcJNGFL7iPEuajQw7vxMHUkXylu4/vhCkJGXsgRmxqMKXUpT6FEgl0g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@oxc-project/types": "=0.124.0",
"@rolldown/pluginutils": "1.0.0-rc.15"
"@oxc-project/types": "=0.126.0",
"@rolldown/pluginutils": "1.0.0-rc.16"
},
"bin": {
"rolldown": "bin/cli.mjs"
@@ -2439,21 +2440,21 @@
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
"@rolldown/binding-android-arm64": "1.0.0-rc.15",
"@rolldown/binding-darwin-arm64": "1.0.0-rc.15",
"@rolldown/binding-darwin-x64": "1.0.0-rc.15",
"@rolldown/binding-freebsd-x64": "1.0.0-rc.15",
"@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15",
"@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15",
"@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15",
"@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15",
"@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15",
"@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15",
"@rolldown/binding-linux-x64-musl": "1.0.0-rc.15",
"@rolldown/binding-openharmony-arm64": "1.0.0-rc.15",
"@rolldown/binding-wasm32-wasi": "1.0.0-rc.15",
"@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15",
"@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15"
"@rolldown/binding-android-arm64": "1.0.0-rc.16",
"@rolldown/binding-darwin-arm64": "1.0.0-rc.16",
"@rolldown/binding-darwin-x64": "1.0.0-rc.16",
"@rolldown/binding-freebsd-x64": "1.0.0-rc.16",
"@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.16",
"@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.16",
"@rolldown/binding-linux-arm64-musl": "1.0.0-rc.16",
"@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.16",
"@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.16",
"@rolldown/binding-linux-x64-gnu": "1.0.0-rc.16",
"@rolldown/binding-linux-x64-musl": "1.0.0-rc.16",
"@rolldown/binding-openharmony-arm64": "1.0.0-rc.16",
"@rolldown/binding-wasm32-wasi": "1.0.0-rc.16",
"@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.16",
"@rolldown/binding-win32-x64-msvc": "1.0.0-rc.16"
}
},
"node_modules/run-parallel": {
@@ -2812,17 +2813,17 @@
"license": "MIT"
},
"node_modules/vite": {
"version": "8.0.8",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.8.tgz",
"integrity": "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==",
"version": "8.0.9",
"resolved": "https://registry.npmjs.org/vite/-/vite-8.0.9.tgz",
"integrity": "sha512-t7g7GVRpMXjNpa67HaVWI/8BWtdVIQPCL2WoozXXA7LBGEFK4AkkKkHx2hAQf5x1GZSlcmEDPkVLSGahxnEEZw==",
"dev": true,
"license": "MIT",
"dependencies": {
"lightningcss": "^1.32.0",
"picomatch": "^4.0.4",
"postcss": "^8.5.8",
"rolldown": "1.0.0-rc.15",
"tinyglobby": "^0.2.15"
"postcss": "^8.5.10",
"rolldown": "1.0.0-rc.16",
"tinyglobby": "^0.2.16"
},
"bin": {
"vite": "bin/vite.js"
+9
View File
@@ -162,6 +162,15 @@
<div class="md:flex-1">
<x-form-input name="search" label="Pencarian" :value="$search" placeholder="Cari kelas..." />
</div>
<div class="md:flex-1">
<label for="academic_year_id" class="mb-2 block text-sm font-medium text-slate-700">Tahun Ajaran</label>
<select id="academic_year_id" name="academic_year_id" onchange="this.form.submit()" class="w-full rounded-2xl border border-slate-200 bg-white px-4 py-3 text-sm text-slate-700 focus:border-indigo-300 focus:outline-none focus:ring-2 focus:ring-indigo-100">
<option value="">TA berjalan ({{ $academicYears->firstWhere('is_active', true)?->name ?? '-' }})</option>
@foreach ($academicYears as $ay)
<option value="{{ $ay->id }}" @selected($academicYearId === $ay->id)>{{ $ay->name }}{{ $ay->is_active ? ' (aktif)' : '' }}</option>
@endforeach
</select>
</div>
<div class="flex items-end gap-3">
<button type="submit" class="rounded-2xl bg-slate-900 px-5 py-3 text-sm font-semibold text-white transition hover:bg-slate-800">Cari</button>
<a href="{{ route('classes.index') }}" class="rounded-2xl border border-slate-200 px-5 py-3 text-sm font-semibold text-slate-700 transition hover:bg-slate-50">Reset</a>
+28 -19
View File
@@ -199,40 +199,49 @@
</div>
<div class="rounded-3xl border border-sky-200 bg-white p-5 shadow-sm shadow-sky-100/50 sm:p-6">
@php
// Jenis dokumen kelulusan — sesuaikan dengan kolom arsip di database (student_graduations)
$graduationDocs = [
['label' => 'SKL', 'path' => 'skl_file_path', 'name' => 'skl_file_name', 'route' => 'skl', 'icon' => 'fa-solid fa-file-lines'],
['label' => 'Ijazah', 'path' => 'ijazah_file_path', 'name' => 'ijazah_file_name', 'route' => 'ijazah', 'icon' => 'fa-solid fa-graduation-cap'],
['label' => 'Transkrip Nilai', 'path' => 'transcript_file_path', 'name' => 'transcript_file_name', 'route' => 'transcript', 'icon' => 'fa-solid fa-table-list'],
['label' => 'Sertifikat UKK', 'path' => 'ukk_certificate_file_path', 'name' => 'ukk_certificate_file_name', 'route' => 'ukk-certificate', 'icon' => 'fa-solid fa-award'],
['label' => 'Sertifikat LSP', 'path' => 'lsp_certificate_file_path', 'name' => 'lsp_certificate_file_name', 'route' => 'lsp-certificate', 'icon' => 'fa-solid fa-certificate'],
];
$gradRec = $student->public_graduation_record;
@endphp
<div class="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
<div>
<h3 class="text-base font-semibold text-slate-900">Layanan Dokumen Kelulusan</h3>
<p class="mt-1 text-sm text-slate-500">Unduh SKL atau ijazah jika dokumen sudah tersedia di arsip sekolah.</p>
<p class="mt-1 text-sm text-slate-500">Unduh dokumen kelulusan (SKL, ijazah, transkrip, sertifikat) jika sudah tersedia di arsip sekolah.</p>
</div>
<div class="rounded-full bg-sky-100 px-4 py-2 text-xs font-semibold uppercase tracking-[0.14em] text-sky-700">
To The Point
</div>
</div>
<div class="mt-5 grid gap-4 md:grid-cols-2">
<div class="rounded-2xl border {{ $student->public_graduation_record?->skl_file_path ? 'border-emerald-200 bg-emerald-50' : 'border-slate-200 bg-slate-50' }} px-4 py-4 text-sm">
<div class="font-semibold {{ $student->public_graduation_record?->skl_file_path ? 'text-emerald-700' : 'text-slate-700' }}">SKL</div>
<div class="mt-1 text-xs {{ $student->public_graduation_record?->skl_file_path ? 'text-emerald-600' : 'text-slate-500' }}">{{ $student->public_graduation_record?->skl_file_name ?: 'Dokumen belum tersedia' }}</div>
<div class="mt-5 grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
@foreach ($graduationDocs as $doc)
@php
$available = $gradRec && $gradRec->{$doc['path']};
@endphp
<div class="rounded-2xl border {{ $available ? 'border-emerald-200 bg-emerald-50' : 'border-slate-200 bg-slate-50' }} px-4 py-4 text-sm">
<div class="flex items-center gap-2">
<i class="{{ $doc['icon'] }} {{ $available ? 'text-emerald-600' : 'text-slate-400' }}"></i>
<div class="font-semibold {{ $available ? 'text-emerald-700' : 'text-slate-700' }}">{{ $doc['label'] }}</div>
</div>
<div class="mt-1 text-xs {{ $available ? 'text-emerald-600' : 'text-slate-500' }}">{{ $available ? $gradRec->{$doc['name']} : 'Dokumen belum tersedia' }}</div>
<div class="mt-4">
@if ($student->public_graduation_record?->skl_file_path)
<a href="{{ route('public.students.graduation-documents.download', [$student, 'skl']) }}" class="inline-flex items-center rounded-2xl bg-sky-600 px-4 py-2.5 text-xs font-semibold text-white transition hover:bg-sky-700">Download SKL</a>
@else
<span class="inline-flex items-center rounded-2xl border border-slate-200 px-4 py-2.5 text-xs font-semibold text-slate-400">Belum tersedia</span>
@endif
</div>
</div>
<div class="rounded-2xl border {{ $student->public_graduation_record?->ijazah_file_path ? 'border-emerald-200 bg-emerald-50' : 'border-slate-200 bg-slate-50' }} px-4 py-4 text-sm">
<div class="font-semibold {{ $student->public_graduation_record?->ijazah_file_path ? 'text-emerald-700' : 'text-slate-700' }}">Ijazah</div>
<div class="mt-1 text-xs {{ $student->public_graduation_record?->ijazah_file_path ? 'text-emerald-600' : 'text-slate-500' }}">{{ $student->public_graduation_record?->ijazah_file_name ?: 'Dokumen belum tersedia' }}</div>
<div class="mt-4">
@if ($student->public_graduation_record?->ijazah_file_path)
<a href="{{ route('public.students.graduation-documents.download', [$student, 'ijazah']) }}" class="inline-flex items-center rounded-2xl bg-sky-600 px-4 py-2.5 text-xs font-semibold text-white transition hover:bg-sky-700">Download Ijazah</a>
@if ($available)
<a href="{{ route('public.students.graduation-documents.download', [$student, $doc['route']]) }}" class="inline-flex items-center gap-2 rounded-2xl bg-sky-600 px-4 py-2.5 text-xs font-semibold text-white transition hover:bg-sky-700">
<i class="fa-solid fa-download"></i> Download {{ $doc['label'] }}
</a>
@else
<span class="inline-flex items-center rounded-2xl border border-slate-200 px-4 py-2.5 text-xs font-semibold text-slate-400">Belum tersedia</span>
@endif
</div>
</div>
@endforeach
</div>
</div>
@else
@@ -148,9 +148,6 @@
<li><strong>date_of_birth</strong> — tanggal lahir</li>
<li><strong>religion</strong> — agama</li>
<li><strong>nationality</strong> — kewarganegaraan</li>
<li><strong>family_card_number</strong> — no. kartu keluarga</li>
<li><strong>child_order</strong> — anak ke</li>
<li><strong>number_of_siblings</strong> — jumlah saudara</li>
<li><strong>phone_number</strong> — nomor HP</li>
<li><strong>email</strong> — email</li>
<li><strong>address</strong> — alamat</li>
@@ -165,9 +162,6 @@
<li><strong>entry_date</strong> — tanggal masuk</li>
<li><strong>status</strong> — status siswa</li>
<li><strong>notes</strong> — catatan</li>
<li><strong>parent_father_*</strong> — data ayah</li>
<li><strong>parent_mother_*</strong> — data ibu</li>
<li><strong>parent_guardian_*</strong> — data wali</li>
</ul>
</x-master-card>
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;
/**
* REPRO SEMENTARA: memicu route update siswa keluar terhadap DB PRODUKSI.
* Tidak memakai RefreshDatabase. Data tidak diubah (nilai dikirim kosong).
* Hanya untuk menangkap exception yang bikin 500 di /students/keluar/{id} POST.
*/
class ReproExitTest extends TestCase
{
use WithoutMiddleware;
public function test_repro_update_exit_31(): void
{
// Pakai DB produksi
config(['database.default' => 'mysql']);
\Illuminate\Support\Facades\DB::purge('mysql');
$exit = \App\Models\StudentExit::find(31);
$this->assertNotNull($exit, 'exit 31 tidak ditemukan');
$res = $this->patch("/students/keluar/{$exit->id}", [
'exit_date' => '',
'exit_reason' => '',
]);
fwrite(STDERR, 'STATUS: '.$res->getStatusCode()."\n");
if (isset($res->exception)) {
fwrite(STDERR, 'EXC: '.get_class($res->exception).': '.$res->exception->getMessage()."\n");
fwrite(STDERR, 'AT: '.$res->exception->getFile().':'.$res->exception->getLine()."\n");
}
$this->assertTrue(true);
}
}