Initial commit

This commit is contained in:
2026-04-12 06:24:30 +00:00
commit 007f107be6
213 changed files with 25576 additions and 0 deletions
@@ -0,0 +1,296 @@
@php
try {
$branding = \App\Models\AppSetting::branding();
} catch (\Throwable $e) {
$branding = \App\Models\AppSetting::brandingDefaults();
}
@endphp
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Form Pelengkapan Data Siswa - {{ $branding['app_name'] ?? 'Database Kesiswaan' }}</title>
@if (!empty($branding['app_favicon']))
<link rel="icon" type="image/png" href="{{ asset('storage/' . $branding['app_favicon']) }}">
@endif
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="min-h-screen bg-slate-100 text-slate-900">
<div
x-data="studentSelfServiceForm()"
x-init="init()"
class="mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8"
>
<script>
function studentSelfServiceForm() {
return {
selectedProvince: @js((string) old('province_id', $student->province_id ?? '')),
selectedRegency: @js((string) old('regency_id', $student->regency_id ?? '')),
selectedDistrict: @js((string) old('district_id', $student->district_id ?? '')),
selectedVillage: @js((string) old('village_id', $student->village_id ?? '')),
regencies: [],
districts: [],
villages: [],
loadingRegencies: false,
loadingDistricts: false,
loadingVillages: false,
async init() {
if (this.selectedProvince) await this.loadRegencies(false);
if (this.selectedRegency) await this.loadDistricts(false);
if (this.selectedDistrict) await this.loadVillages(false);
},
async loadRegencies(reset = true) {
if (reset) {
this.selectedRegency = '';
this.selectedDistrict = '';
this.selectedVillage = '';
this.districts = [];
this.villages = [];
}
this.regencies = [];
if (!this.selectedProvince) return;
this.loadingRegencies = true;
const response = await fetch(`/regions/provinces/${this.selectedProvince}/regencies`);
this.regencies = await response.json();
this.loadingRegencies = false;
},
async loadDistricts(reset = true) {
if (reset) {
this.selectedDistrict = '';
this.selectedVillage = '';
this.villages = [];
}
this.districts = [];
if (!this.selectedRegency) return;
this.loadingDistricts = true;
const response = await fetch(`/regions/regencies/${this.selectedRegency}/districts`);
this.districts = await response.json();
this.loadingDistricts = false;
},
async loadVillages(reset = true) {
if (reset) this.selectedVillage = '';
this.villages = [];
if (!this.selectedDistrict) return;
this.loadingVillages = true;
const response = await fetch(`/regions/districts/${this.selectedDistrict}/villages`);
this.villages = await response.json();
this.loadingVillages = false;
}
}
}
</script>
<div class="mb-8 flex flex-col gap-4 rounded-[2rem] bg-white p-6 shadow-sm shadow-slate-200 lg:flex-row lg:items-center lg:justify-between">
<div>
<div class="text-sm font-semibold uppercase tracking-[0.22em] text-indigo-600">Form Pelengkapan Data</div>
<h1 class="mt-2 text-3xl font-bold text-slate-900">{{ $student->full_name }}</h1>
<p class="mt-2 text-sm text-slate-500">Lengkapi data diri dengan benar. Data akademik inti ditampilkan sebagai referensi dan tidak bisa diubah dari sini.</p>
</div>
<div class="rounded-2xl border border-slate-200 bg-slate-50 px-5 py-4 text-sm text-slate-600">
<div><strong>NIS:</strong> {{ $student->student_number ?: '-' }}</div>
<div><strong>NISN:</strong> {{ $student->nisn ?: '-' }}</div>
<div><strong>Tahun Angkatan:</strong> {{ $student->academicYear?->name ?: '-' }}</div>
<div><strong>Program Keahlian:</strong> {{ $student->department?->name ?: '-' }}</div>
<div><strong>Kelas:</strong> {{ $student->classRoom?->name ?: '-' }}</div>
</div>
</div>
@if (session('success'))
<div class="mb-6 rounded-2xl border border-emerald-200 bg-emerald-50 px-5 py-4 text-sm text-emerald-700">
{{ session('success') }}
</div>
@endif
@if ($errors->any())
<div class="mb-6 rounded-2xl border border-rose-200 bg-rose-50 px-5 py-4 text-sm text-rose-700">
<ul class="list-disc space-y-1 pl-5">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="POST" action="{{ route('public.student-self-service.update') }}" class="space-y-6">
@csrf
<div class="grid grid-cols-1 gap-6 xl:grid-cols-2">
<div class="rounded-[2rem] bg-white p-6 shadow-sm shadow-slate-200">
<h2 class="text-lg font-semibold text-slate-900">Identitas Siswa</h2>
<div class="mt-5 grid grid-cols-1 gap-5 md:grid-cols-2">
<div class="md:col-span-2">
<label class="mb-2 block text-sm font-medium text-slate-700">Nama Lengkap</label>
<input name="full_name" type="text" value="{{ old('full_name', $student->full_name) }}" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm" required>
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Jenis Kelamin</label>
<select name="gender" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm" required>
<option value="">-- Pilih --</option>
@foreach ($genders as $value => $label)
<option value="{{ $value }}" @selected(old('gender', $student->gender) === $value)>{{ $label }}</option>
@endforeach
</select>
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Agama</label>
<select name="religion" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
<option value="">-- Pilih --</option>
@foreach ($religions as $value => $label)
<option value="{{ $value }}" @selected(old('religion', $student->religion) === $value)>{{ $label }}</option>
@endforeach
</select>
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Tempat Lahir</label>
<input name="place_of_birth" type="text" value="{{ old('place_of_birth', $student->place_of_birth) }}" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Tanggal Lahir</label>
<input name="date_of_birth" type="date" value="{{ old('date_of_birth', optional($student->date_of_birth)->format('Y-m-d')) }}" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Kewarganegaraan</label>
<input name="nationality" type="text" value="{{ old('nationality', $student->nationality) }}" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">No. Kartu Keluarga</label>
<input name="family_card_number" type="text" value="{{ old('family_card_number', $student->family_card_number) }}" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Anak Ke</label>
<input name="child_order" type="number" value="{{ old('child_order', $student->child_order) }}" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Jumlah Saudara</label>
<input name="number_of_siblings" type="number" value="{{ old('number_of_siblings', $student->number_of_siblings) }}" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">No. HP</label>
<input name="phone_number" type="text" value="{{ old('phone_number', $student->phone_number) }}" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Email</label>
<input name="email" type="email" value="{{ old('email', $student->email) }}" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
</div>
</div>
<div class="rounded-[2rem] bg-white p-6 shadow-sm shadow-slate-200">
<h2 class="text-lg font-semibold text-slate-900">Alamat</h2>
<div class="mt-5 grid grid-cols-1 gap-5 md:grid-cols-2">
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Provinsi</label>
<select name="province_id" x-model="selectedProvince" @change="loadRegencies()" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
<option value="">-- Pilih Provinsi --</option>
@foreach ($provinces as $id => $name)
<option value="{{ $id }}">{{ $name }}</option>
@endforeach
</select>
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Kabupaten/Kota</label>
<select name="regency_id" x-model="selectedRegency" @change="loadDistricts()" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
<option value="" x-text="loadingRegencies ? 'Memuat...' : '-- Pilih Kabupaten/Kota --'"></option>
<template x-for="regency in regencies" :key="regency.id">
<option :value="regency.id" x-text="regency.name"></option>
</template>
</select>
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Kecamatan</label>
<select name="district_id" x-model="selectedDistrict" @change="loadVillages()" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
<option value="" x-text="loadingDistricts ? 'Memuat...' : '-- Pilih Kecamatan --'"></option>
<template x-for="district in districts" :key="district.id">
<option :value="district.id" x-text="district.name"></option>
</template>
</select>
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Desa/Kelurahan</label>
<select name="village_id" x-model="selectedVillage" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
<option value="" x-text="loadingVillages ? 'Memuat...' : '-- Pilih Desa/Kelurahan --'"></option>
<template x-for="village in villages" :key="village.id">
<option :value="village.id" x-text="village.name"></option>
</template>
</select>
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Kode Pos</label>
<input name="postal_code" type="text" value="{{ old('postal_code', $student->postal_code) }}" class="h-12 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div class="md:col-span-2">
<label class="mb-2 block text-sm font-medium text-slate-700">Alamat Lengkap</label>
<textarea name="address" rows="4" class="w-full rounded-2xl border border-slate-200 px-4 py-3 text-sm">{{ old('address', $student->address) }}</textarea>
</div>
</div>
</div>
</div>
<div class="rounded-[2rem] bg-white p-6 shadow-sm shadow-slate-200">
<h2 class="text-lg font-semibold text-slate-900">Data Orang Tua / Wali</h2>
<div class="mt-6 grid grid-cols-1 gap-6 xl:grid-cols-3">
@foreach ($parentRelationLabels as $relationType => $label)
@php
$parent = $student->parents->firstWhere('relation_type', $relationType);
@endphp
<div class="rounded-3xl border border-slate-200 bg-slate-50 p-5">
<h3 class="text-base font-semibold text-slate-800">{{ $label }}</h3>
<div class="mt-4 space-y-4">
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Nama</label>
<input name="parents[{{ $relationType }}][name]" type="text" value="{{ old("parents.$relationType.name", $parent?->name) }}" class="h-11 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">NIK</label>
<input name="parents[{{ $relationType }}][nik]" type="text" value="{{ old("parents.$relationType.nik", $parent?->nik) }}" class="h-11 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Tahun Lahir</label>
<input name="parents[{{ $relationType }}][birth_year]" type="number" value="{{ old("parents.$relationType.birth_year", $parent?->birth_year) }}" class="h-11 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Pendidikan</label>
<select name="parents[{{ $relationType }}][education]" class="h-11 w-full rounded-2xl border border-slate-200 px-4 text-sm">
<option value="">-- Pilih Pendidikan --</option>
@foreach ($educationOptions as $value => $label)
<option value="{{ $value }}" @selected(old("parents.$relationType.education", $parent?->education) === $value)>{{ $label }}</option>
@endforeach
</select>
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Pekerjaan</label>
<input name="parents[{{ $relationType }}][occupation]" type="text" value="{{ old("parents.$relationType.occupation", $parent?->occupation) }}" class="h-11 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">No. HP</label>
<input name="parents[{{ $relationType }}][phone_number]" type="text" value="{{ old("parents.$relationType.phone_number", $parent?->phone_number) }}" class="h-11 w-full rounded-2xl border border-slate-200 px-4 text-sm">
</div>
<div>
<label class="mb-2 block text-sm font-medium text-slate-700">Alamat</label>
<textarea name="parents[{{ $relationType }}][address]" rows="3" class="w-full rounded-2xl border border-slate-200 px-4 py-3 text-sm">{{ old("parents.$relationType.address", $parent?->address) }}</textarea>
</div>
<label class="inline-flex items-center gap-3 text-sm text-slate-700">
<input type="hidden" name="parents[{{ $relationType }}][is_alive]" value="0">
<input type="checkbox" name="parents[{{ $relationType }}][is_alive]" value="1" class="rounded border-slate-300 text-indigo-600 focus:ring-indigo-500" @checked(old("parents.$relationType.is_alive", $parent?->is_alive ?? true))>
<span>Masih hidup</span>
</label>
</div>
</div>
@endforeach
</div>
</div>
<div class="flex flex-col gap-3 rounded-[2rem] bg-white p-6 shadow-sm shadow-slate-200 sm:flex-row sm:justify-end">
<button type="submit" name="submit_action" value="draft" class="inline-flex items-center justify-center rounded-2xl border border-slate-200 px-5 py-3 text-sm font-semibold text-slate-700 transition hover:bg-slate-50">
Simpan Draft
</button>
<button type="submit" name="submit_action" value="submit" class="inline-flex items-center justify-center rounded-2xl bg-indigo-600 px-5 py-3 text-sm font-semibold text-white shadow-lg shadow-indigo-200 transition hover:bg-indigo-700">
Kirim Data
</button>
</div>
</form>
</div>
</body>
</html>
@@ -0,0 +1,112 @@
@php
try {
$branding = \App\Models\AppSetting::branding();
} catch (\Throwable $e) {
$branding = \App\Models\AppSetting::brandingDefaults();
}
$publicLogo = $branding['public_portal_logo'] ?: ($branding['app_logo'] ?? null);
@endphp
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Pelengkapan Data Siswa - {{ $branding['app_name'] ?? 'Database Kesiswaan' }}</title>
@if (!empty($branding['app_favicon']))
<link rel="icon" type="image/png" href="{{ asset('storage/' . $branding['app_favicon']) }}">
@endif
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
<body class="min-h-screen bg-slate-100 font-sans text-slate-900 antialiased">
<div class="relative min-h-screen overflow-hidden bg-[radial-gradient(circle_at_top_left,_rgba(99,102,241,0.18),_transparent_30%),radial-gradient(circle_at_bottom_right,_rgba(14,165,233,0.12),_transparent_30%)]">
<div class="absolute inset-0 bg-[linear-gradient(to_bottom,_rgba(255,255,255,0.78),_rgba(248,250,252,0.98))]"></div>
<div class="relative mx-auto max-w-6xl px-4 py-10 sm:px-6 lg:px-8">
<div class="mb-8 flex justify-center text-center">
<div class="inline-flex items-center gap-3 rounded-full border border-indigo-100 bg-white/90 px-4 py-2 shadow-sm shadow-slate-200/60">
<div class="flex h-9 w-9 items-center justify-center overflow-hidden rounded-2xl bg-indigo-600 text-sm font-bold text-white shadow-lg shadow-indigo-200">
@if (!empty($publicLogo))
<img src="{{ asset('storage/' . $publicLogo) }}" alt="{{ $branding['app_name'] }}" class="h-full w-full object-contain bg-white p-1">
@else
{{ $branding['app_short_name'] ?? 'DK' }}
@endif
</div>
<div class="text-left">
<div class="text-sm font-semibold text-slate-900">{{ $branding['app_name'] ?? 'Database Kesiswaan' }}</div>
<div class="text-xs text-slate-500">Portal Pelengkapan Siswa</div>
</div>
</div>
</div>
<div class="flex min-h-[48vh] items-center justify-center">
<div class="mx-auto w-full max-w-4xl overflow-hidden rounded-[32px] border border-white/80 bg-white/95 shadow-[0_30px_80px_-35px_rgba(15,23,42,0.25)]">
<div class="border-b border-slate-100 bg-gradient-to-r from-indigo-50 via-white to-sky-50 px-6 py-6 sm:px-8">
<div class="max-w-2xl">
<div class="text-xs font-semibold uppercase tracking-[0.18em] text-indigo-500">Verifikasi Identitas</div>
<h2 class="mt-2 text-2xl font-bold text-slate-900">Lengkapi data siswa secara mandiri</h2>
<p class="mt-2 text-sm leading-6 text-slate-500">
Masukkan NIS atau NISN dan kode akses dari sekolah untuk melanjutkan ke form pelengkapan data siswa.
</p>
</div>
</div>
<div class="p-6 sm:p-8">
<div class="mb-6 rounded-2xl border border-indigo-100 bg-indigo-50/70 px-4 py-4 text-sm text-indigo-700">
<div class="font-semibold text-indigo-900">Petunjuk singkat</div>
<p class="mt-1">Gunakan data yang benar sesuai dokumen resmi. Jika ada data yang tidak cocok, hubungi admin sekolah atau wali kelas.</p>
</div>
@if ($errors->any())
<div class="mb-6 rounded-2xl border border-rose-200 bg-rose-50 px-5 py-4 text-sm text-rose-700">
<ul class="list-disc space-y-1 pl-5">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="POST" action="{{ route('public.student-self-service.verify') }}" class="space-y-4">
@csrf
<div class="flex flex-col gap-4 lg:flex-row lg:items-end">
<div class="flex-1">
<label for="identity_number" class="mb-2 block text-sm font-semibold text-slate-700">NIS atau NISN</label>
<input
id="identity_number"
name="identity_number"
type="text"
value="{{ old('identity_number') }}"
class="h-[50px] w-full rounded-2xl border border-slate-200 bg-white px-4 text-sm text-slate-700 placeholder:text-slate-400 focus:border-indigo-300 focus:outline-none focus:ring-2 focus:ring-indigo-100"
placeholder="Masukkan NIS atau NISN"
required
>
</div>
<div class="flex-1">
<label for="access_code" class="mb-2 block text-sm font-semibold text-slate-700">Kode Akses</label>
<input
id="access_code"
name="access_code"
type="text"
value="{{ old('access_code') }}"
class="h-[50px] w-full rounded-2xl border border-slate-200 bg-white px-4 uppercase text-sm text-slate-700 placeholder:text-slate-400 focus:border-indigo-300 focus:outline-none focus:ring-2 focus:ring-indigo-100"
placeholder="Masukkan kode akses dari sekolah"
required
>
</div>
<div class="lg:pb-[1px]">
<button type="submit" class="rounded-xl bg-indigo-600 px-5 py-3 text-sm font-semibold text-white transition hover:bg-indigo-700">
Lanjut
</button>
</div>
</div>
<p class="text-xs text-slate-400">Setelah verifikasi berhasil, Anda dapat melengkapi biodata, alamat, dan data orang tua/wali.</p>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>