MIF_E31232406/resources/views/rt/calon-penerima/create.blade.php

474 lines
27 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<x-app-layout>
<x-slot name="header">
<div>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">Form Pendataan Warga</h2>
<p class="text-sm text-gray-500 mt-0.5">Isi semua data dengan benar sebelum menyimpan.</p>
</div>
</x-slot>
<style>
.input-field { font-size: 16px !important; }
@media (min-width: 640px) { .input-field { font-size: 14px !important; } }
@media (max-width: 480px) {
.action-row { flex-direction: column-reverse !important; }
.action-row a,
.action-row button { width: 100%; justify-content: center; text-align: center; }
}
@media (max-width: 640px) {
.section-body { padding: 14px 14px !important; }
.section-head { padding: 10px 14px !important; }
}
</style>
@if ($errors->any())
<div class="mb-4 rounded-xl border border-red-200 bg-red-50 p-4 text-sm text-red-700">
<div class="font-semibold mb-2">Gagal menyimpan:</div>
<ul class="list-disc ps-5 space-y-1">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@if (session('error'))
<div class="mb-4 rounded-xl border border-red-200 bg-red-50 p-4 text-sm text-red-700">
{{ session('error') }}
</div>
@endif
@if (session('success'))
<div class="mb-4 rounded-xl border border-green-200 bg-green-50 p-4 text-sm text-green-700">
{{ session('success') }}
</div>
@endif
<form action="{{ route('rt.calon-penerima.store') }}" method="POST" id="formPendataan" novalidate enctype="multipart/form-data">
@csrf
{{-- SECTION 1: Data Identitas --}}
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 mb-4 overflow-hidden">
<div class="section-head px-5 py-3 border-b border-gray-100 flex items-center gap-2 bg-gray-50">
<div class="w-1 h-4 bg-blue-600 rounded-full"></div>
<h3 class="text-sm font-semibold text-gray-700">Data Identitas</h3>
</div>
<div class="section-body p-5 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
@php
$myRtId = auth()->user()->rt_id ?? (auth()->user()->rt->id ?? null);
@endphp
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
RT <span class="text-red-500">*</span>
</label>
<select
id="rt_id_display"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-100"
disabled
>
@foreach(($rts ?? []) as $rt)
<option
value="{{ $rt->id }}"
{{ (string)$rt->id === (string)$myRtId ? 'selected' : '' }}
>
RT {{ str_pad($rt->nomor_rt, 3, '0', STR_PAD_LEFT) }} - {{ $rt->dusun->nama_dusun ?? '' }}
</option>
@endforeach
</select>
<input type="hidden" name="rt_id" id="rt_id" value="{{ $myRtId }}">
<p class="error-msg text-xs text-red-500 mt-1 hidden">RT wajib dipilih.</p>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
No. KK <span class="text-red-500">*</span>
</label>
<input type="text" name="no_kk" id="no_kk" maxlength="16"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50"
placeholder="16 digit No. KK" required inputmode="numeric">
<p class="error-msg text-xs text-red-500 mt-1 hidden">No. KK harus 16 digit angka.</p>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
NIK <span class="text-red-500">*</span>
</label>
<input type="text" name="nik" id="nik" maxlength="16"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50"
placeholder="16 digit NIK" required inputmode="numeric">
<p class="error-msg text-xs text-red-500 mt-1 hidden">NIK harus tepat 16 digit angka.</p>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Nama Lengkap <span class="text-red-500">*</span>
</label>
<input type="text" name="nama_lengkap" id="nama_lengkap"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50"
placeholder="Nama sesuai KTP" required>
<p class="error-msg text-xs text-red-500 mt-1 hidden">Nama lengkap wajib diisi.</p>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Jenis Kelamin <span class="text-red-500">*</span>
</label>
<select name="jenis_kelamin"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50">
<option value="Laki-laki">Laki-laki</option>
<option value="Perempuan">Perempuan</option>
</select>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Tempat Lahir <span class="text-red-500">*</span>
</label>
<input type="text" name="tempat_lahir" id="tempat_lahir"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50"
placeholder="Kota/Kabupaten" required>
<p class="error-msg text-xs text-red-500 mt-1 hidden">Tempat lahir wajib diisi.</p>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Tanggal Lahir <span class="text-red-500">*</span>
</label>
<input type="date" name="tanggal_lahir" id="tanggal_lahir"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50"
required>
<p class="error-msg text-xs text-red-500 mt-1 hidden">Tanggal lahir wajib diisi.</p>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Usia <span class="text-red-500">*</span>
</label>
<input type="number" name="usia" id="usia" min="0" max="150"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50"
placeholder="Otomatis dari tanggal lahir" required inputmode="numeric">
<p class="error-msg text-xs text-red-500 mt-1 hidden">Usia harus antara 0150 tahun.</p>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Status Perkawinan <span class="text-red-500">*</span>
</label>
<select name="status_perkawinan" id="status_perkawinan"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50">
<option value="">-- Pilih --</option>
<option value="Belum Kawin">Belum Kawin</option>
<option value="Kawin">Kawin</option>
<option value="Cerai Hidup">Cerai Hidup</option>
<option value="Cerai Mati">Cerai Mati</option>
</select>
<p class="error-msg text-xs text-red-500 mt-1 hidden">Status perkawinan wajib dipilih.</p>
</div>
</div>
</div>
{{-- SECTION 2: Data Tempat Tinggal --}}
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 mb-4 overflow-hidden">
<div class="section-head px-5 py-3 border-b border-gray-100 flex items-center gap-2 bg-gray-50">
<div class="w-1 h-4 bg-emerald-500 rounded-full"></div>
<h3 class="text-sm font-semibold text-gray-700">Data Tempat Tinggal</h3>
</div>
<div class="section-body p-5 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div class="field-group lg:col-span-2">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Alamat <span class="text-red-500">*</span>
</label>
<input type="text" name="alamat" id="alamat"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50"
placeholder="Jalan, nomor rumah, RT/RW" required>
<p class="error-msg text-xs text-red-500 mt-1 hidden">Alamat wajib diisi.</p>
</div>
@php
$myDusunName = auth()->user()->rt->dusun->nama_dusun ?? '';
@endphp
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Dusun <span class="text-red-500">*</span>
</label>
<input type="text" id="desa_display"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-100"
value="{{ $myDusunName }}" readonly>
<input type="hidden" name="desa" id="desa" value="{{ $myDusunName }}">
<p class="error-msg text-xs text-red-500 mt-1 hidden">Dusun wajib diisi.</p>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Aset Kepemilikan <span class="text-red-500">*</span>
</label>
<input type="text" name="aset_kepemilikan" id="aset_kepemilikan"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50"
placeholder="Misal: Rumah, Motor, dll" required>
<p class="error-msg text-xs text-red-500 mt-1 hidden">Aset kepemilikan wajib diisi.</p>
</div>
</div>
</div>
{{-- SECTION 3: Data Ekonomi --}}
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 mb-4 overflow-hidden">
<div class="section-head px-5 py-3 border-b border-gray-100 flex items-center gap-2 bg-gray-50">
<div class="w-1 h-4 bg-amber-500 rounded-full"></div>
<h3 class="text-sm font-semibold text-gray-700">Data Ekonomi</h3>
</div>
<div class="section-body p-5 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Pekerjaan <span class="text-red-500">*</span>
</label>
<input type="text" name="pekerjaan" id="pekerjaan"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50"
placeholder="Jenis pekerjaan" required>
<p class="error-msg text-xs text-red-500 mt-1 hidden">Pekerjaan wajib diisi.</p>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Penghasilan (Rp) <span class="text-red-500">*</span>
</label>
<input type="number" step="0.01" name="penghasilan" id="penghasilan" min="0"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50"
placeholder="0" required inputmode="decimal">
<p class="error-msg text-xs text-red-500 mt-1 hidden">Penghasilan tidak boleh negatif.</p>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Jumlah Tanggungan <span class="text-red-500">*</span>
</label>
<input type="number" name="jumlah_tanggungan" id="jumlah_tanggungan" min="0"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50"
placeholder="Jumlah orang" required inputmode="numeric">
<p class="error-msg text-xs text-red-500 mt-1 hidden">Jumlah tanggungan tidak boleh negatif.</p>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Menerima Bantuan Lain? <span class="text-red-500">*</span>
</label>
<select name="bantuan_lain"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50">
<option value="tidak">Tidak</option>
<option value="ya">Ya</option>
</select>
</div>
</div>
</div>
{{-- SECTION 4: Kondisi Tempat Tinggal --}}
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 mb-4 overflow-hidden">
<div class="section-head px-5 py-3 border-b border-gray-100 flex items-center gap-2 bg-gray-50">
<div class="w-1 h-4 bg-purple-500 rounded-full"></div>
<h3 class="text-sm font-semibold text-gray-700">Kondisi Tempat Tinggal</h3>
</div>
<div class="section-body p-5 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Kondisi Rumah <span class="text-red-500">*</span>
</label>
<select name="kondisi_rumah" id="kondisi_rumah"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50">
<option value="Layak">Layak</option>
<option value="Sedang">Sedang</option>
<option value="Tidak Layak">Tidak Layak</option>
</select>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Meteran Listrik <span class="text-red-500">*</span>
</label>
<select name="meteran_listrik" id="meteran_listrik"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50">
<option value="450VA">450VA</option>
<option value="900VA">900VA</option>
<option value="1300VA+">1300VA+</option>
</select>
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">
Sumber Air <span class="text-red-500">*</span>
</label>
<select name="sumber_air" id="sumber_air"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-gray-50">
<option value="PDAM">PDAM</option>
<option value="Sumur">Sumur</option>
<option value="Sungai">Sungai</option>
</select>
</div>
</div>
</div>
{{-- SECTION 5: Upload Dokumen & Foto --}}
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 mb-5 overflow-hidden">
<div class="section-head px-5 py-3 border-b border-gray-100 flex items-center gap-2 bg-gray-50">
<div class="w-1 h-4 bg-rose-500 rounded-full"></div>
<h3 class="text-sm font-semibold text-gray-700">Upload Dokumen & Foto</h3>
</div>
<div class="section-body p-5 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">Foto Rumah Depan</label>
<input type="file" name="foto_rumah_depan" accept="image/*"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm bg-gray-50">
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">Foto Rumah Belakang</label>
<input type="file" name="foto_rumah_belakang" accept="image/*"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm bg-gray-50">
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">Foto Rumah Kanan</label>
<input type="file" name="foto_rumah_kanan" accept="image/*"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm bg-gray-50">
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">Foto Rumah Kiri</label>
<input type="file" name="foto_rumah_kiri" accept="image/*"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm bg-gray-50">
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">Foto KK</label>
<input type="file" name="foto_kk" accept="image/*"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm bg-gray-50">
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">Foto KTP</label>
<input type="file" name="foto_ktp" accept="image/*"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm bg-gray-50">
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">Foto Rekening Listrik</label>
<input type="file" name="foto_rekening_listrik" accept="image/*,.pdf"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm bg-gray-50">
</div>
<div class="field-group">
<label class="block text-xs font-semibold text-gray-600 mb-1">Foto Meteran Air</label>
<input type="file" name="foto_meteran_air" accept="image/*"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm bg-gray-50">
</div>
<div class="field-group lg:col-span-2">
<label class="block text-xs font-semibold text-gray-600 mb-1">Dokumen Pendukung Lainnya</label>
<input type="file" name="dokumen_pendukung" accept="image/*,.pdf,.doc,.docx"
class="input-field w-full border border-gray-200 rounded-xl px-3 py-2 text-sm bg-gray-50">
</div>
</div>
</div>
{{-- ACTIONS --}}
<div class="action-row flex justify-end gap-3">
<a href="{{ route('rt.calon-penerima.index') }}"
class="px-5 py-2 text-sm font-medium bg-white border border-gray-200 text-gray-600 rounded-xl hover:bg-gray-50 transition">
Batal
</a>
<button type="submit"
class="px-6 py-2 text-sm font-semibold bg-blue-600 text-white rounded-xl hover:bg-blue-700 transition shadow-md shadow-blue-200">
Simpan Data
</button>
</div>
</form>
{{-- TOAST NOTIFIKASI --}}
<div id="toast" class="fixed bottom-5 right-5 z-50 hidden">
<div class="flex items-center gap-3 bg-red-500 text-white text-sm font-medium px-4 py-3 rounded-xl shadow-lg">
<svg class="w-4 h-4 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01M12 3a9 9 0 100 18A9 9 0 0012 3z"/>
</svg>
<span id="toast-msg">Ada field yang tidak valid.</span>
</div>
</div>
<script>
function showError(id, msg) {
const input = document.getElementById(id);
const err = input?.parentElement?.querySelector('.error-msg');
if (input) input.classList.add('border-red-400', 'bg-red-50');
if (err) { err.textContent = msg; err.classList.remove('hidden'); }
}
function clearError(id) {
const input = document.getElementById(id);
const err = input?.parentElement?.querySelector('.error-msg');
if (input) input.classList.remove('border-red-400', 'bg-red-50');
if (err) err.classList.add('hidden');
}
function showToast(msg) {
const t = document.getElementById('toast');
document.getElementById('toast-msg').textContent = msg;
t.classList.remove('hidden');
setTimeout(() => t.classList.add('hidden'), 3500);
}
const rules = {
rt_id: v => v !== '' ? null : 'RT wajib dipilih.',
nik: v => /^\d{16}$/.test(v) ? null : 'NIK harus tepat 16 digit angka.',
no_kk: v => /^\d{16}$/.test(v) ? null : 'No. KK harus tepat 16 digit angka.',
nama_lengkap: v => v.trim().length >= 3 ? null : 'Nama minimal 3 karakter.',
tempat_lahir: v => v.trim().length >= 2 ? null : 'Tempat lahir wajib diisi.',
tanggal_lahir: v => v !== '' ? null : 'Tanggal lahir wajib diisi.',
usia: v => (parseInt(v) >= 0 && parseInt(v) <= 150) ? null : 'Usia harus antara 0150.',
status_perkawinan: v => v !== '' ? null : 'Status perkawinan wajib dipilih.',
alamat: v => v.trim().length >= 5 ? null : 'Alamat minimal 5 karakter.',
desa: v => v.trim().length >= 2 ? null : 'Dusun wajib diisi.',
aset_kepemilikan: v => v.trim().length >= 2 ? null : 'Aset kepemilikan wajib diisi.',
pekerjaan: v => v.trim().length >= 2 ? null : 'Pekerjaan wajib diisi.',
penghasilan: v => parseFloat(v) >= 0 ? null : 'Penghasilan tidak boleh negatif.',
jumlah_tanggungan: v => parseInt(v) >= 0 ? null : 'Jumlah tanggungan tidak boleh negatif.',
};
Object.keys(rules).forEach(id => {
const el = document.getElementById(id);
if (!el) return;
el.addEventListener('blur', () => {
const err = rules[id](el.value);
err ? showError(id, err) : clearError(id);
});
el.addEventListener('input', () => {
if (!el.classList.contains('border-red-400')) return;
const err = rules[id](el.value);
err ? showError(id, err) : clearError(id);
});
el.addEventListener('change', () => {
const err = rules[id](el.value);
err ? showError(id, err) : clearError(id);
});
});
document.getElementById('tanggal_lahir')?.addEventListener('change', function () {
const dob = new Date(this.value);
const today = new Date();
let age = today.getFullYear() - dob.getFullYear();
const m = today.getMonth() - dob.getMonth();
if (m < 0 || (m === 0 && today.getDate() < dob.getDate())) age--;
if (age >= 0 && age <= 150) {
document.getElementById('usia').value = age;
clearError('usia');
}
});
document.getElementById('formPendataan').addEventListener('submit', function (e) {
let valid = true;
Object.keys(rules).forEach(id => {
const el = document.getElementById(id);
if (!el) return;
const err = rules[id](el.value);
if (err) { showError(id, err); valid = false; }
else clearError(id);
});
if (!valid) {
e.preventDefault();
showToast('Mohon perbaiki field yang tidak valid sebelum menyimpan.');
const firstErr = document.querySelector('.border-red-400');
firstErr?.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
});
</script>
</x-app-layout>