# Standar Form Input & Edit (Full Label)

**Aplikasi:** LPK TIP v2 · **Berlaku untuk:** SEMUA halaman create/edit (master, relasi, transaksi, utilitas)
**Tanggal:** 2026-08-14 · **Status:** Standar ✅ · Audit form: 38/38 file ber-label (2 pengecualian minor di bawah)

---

## 1. Prinsip

1. **Full label** — setiap input WAJIB memiliki `<label>` lengkap & deskriptif di atas input. **Placeholder bukan pengganti label** (placeholder hanya petunjuk tambahan).
2. **Label sesuai konten** — teks label = nama field yang dipahami user (mis. "NIK Pegawai", bukan "Nik").
3. **Konsisten** — satu pola styling untuk semua form (label, input, error, grid).
4. **Relasi = combobox** — kolom relasi memakai `x-combobox` searchable (label tampil dari server).
5. **Validasi in-line** — pesan error muncul di bawah field, Bahasa Indonesia.

---

## 2. Pola Kode Standar (Blade)

### 2.1 Field tunggal
```blade
<div>
    <label class="mb-1.5 block text-sm font-medium text-slate-700">
        {{ $label }} @if ($required)<span class="text-red-500">*</span>@endif
    </label>
    <input
        type="text"
        wire:model="field"
        placeholder="Petunjuk tambahan (opsional)"
        class="w-full rounded-xl border border-slate-300 px-4 py-2.5 text-sm outline-none transition focus:border-brand-500 focus:ring-4 focus:ring-brand-500/10"
    >
    @error('field') <p class="mt-1 text-xs text-red-600">{{ $message }}</p> @enderror
</div>
```

### 2.2 Grid responsif
```blade
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
    {{-- field 1 --}}
    {{-- field 2 --}}
    {{-- textarea: md:col-span-2 / lg:col-span-3 --}}
</div>
```

### 2.3 Select relasi (combobox searchable — label server)
```blade
<div>
    <label class="mb-1.5 block text-sm font-medium text-slate-700">Supplier *</label>
    <x-combobox
        :options="$suppliers->map(fn ($s) => ['value' => $s->id, 'label' => $s->name])->values()->all()"
        :value="$form['supplier_id'] ?? ''"
        :label="$suppliers->firstWhere('id', $form['supplier_id'] ?? null)?->name ?? ''"
        name="form.supplier_id"
        placeholder="Cari supplier"
        required
    />
    @error('form.supplier_id') <p class="mt-1 text-xs text-red-600">{{ $message }}</p> @enderror
</div>
```

### 2.4 Checkbox
```blade
<label class="flex items-center gap-2 pt-2 text-sm font-medium text-slate-700">
    <input type="checkbox" wire:model="form.is_active" class="h-4 w-4 rounded border-slate-300 text-brand-600 focus:ring-brand-500">
    Aktif
</label>
```

### 2.5 Angka / uang
```blade
<label class="mb-1.5 block text-sm font-medium text-slate-700">Jumlah *</label>
<input type="number" step="0.01" min="0" wire:model="form.amount"
    class="w-full rounded-xl border border-slate-300 px-4 py-2.5 text-right text-sm tabular-nums outline-none transition focus:border-brand-500 focus:ring-4 focus:ring-brand-500/10">
```

---

## 3. Halaman Form (Kartu)

Gunakan `<x-form-card>` (sudah tersedia) utk konsistensi:
```blade
<x-form-card :title="'Tambah ' . $title" subtitle="Deskripsi singkat form.">
    <x-slot name="actions">
        {{-- tombol Kembali (kiri) --}}
    </x-slot>
    <form wire:submit="save" class="space-y-6">
        {{-- grid field --}}
    </form>
    <x-slot name="footer">
        {{-- tombol Simpan + Batal --}}
    </x-slot>
</x-form-card>
```

---

## 4. Standar Tabel Detail (items)

Lihat `docs/STANDAR-INPUT-DETAIL.md` — ringkasan:
- Header kolom = label (uppercase kecil, bg-slate-50)
- Kolom angka `text-right` + `tabular-nums`
- Relasi → `x-combobox` di dalam cell (dengan label server)
- Tombol Hapus baris = SVG merah; Tambah Baris = SVG `#mi-plus`
- Footer TOTAL rata kanan (cek `colspan`)

---

## 5. Checklist DoD — FORM

| # | Aturan | ✓ |
|---|---|---|
| F1 | Setiap input punya `<label>` lengkap di atas (bukan placeholder-only) | |
| F2 | Label wajib memakai tanda `*` (merah) | |
| F3 | Placeholder hanya petunjuk tambahan (tidak menggantikan label) | |
| F4 | Error message Bahasa Indonesia di bawah field | |
| F5 | Select relasi memakai `x-combobox` (searchable, label server) — dilarang `<select>` panjang | |
| F6 | Angka/uang: `text-right`, `tabular-nums`, `step="0.01"`, `min="0"` | |
| F7 | Checkbox: label di kanan, `rounded border-slate-300 text-brand-600` | |
| F8 | Grid responsif (1 → 2 → 3 kolom) | |
| F9 | Kartu form via `<x-form-card>`; tombol Kembali/Simpan/Batal konsisten | |
| F10 | Header form: judul + subtitle singkat | |
| F11 | Ikon SVG (tanpa emoji); tombol Simpan brand-600, Batal outline | |
| F12 | Validasi server + pesan field; simpan dalam `DB::transaction` | |

---

## 6. Hasil Audit Form (status label)

| Kelompok | File | Label |
|---|---|---|
| Master (MasterCrud) | `master/form.blade.php` | ✅ full label |
| Relasi | `employee-form.blade.php` | ✅ full label |
| Utilitas | `users-form.blade.php`, `change-password`, dll | ✅ full label |
| Transaksi (9 modul) | `transaksi/create.blade.php` | ✅ full label |
| BKK | `cashpayment-form.blade.php` | ✅ full label + total |
| Material | `material/form.blade.php` | ✅ full label |
| Solar / Gudang | `solar-*`, `material-*`, `stock-*` | ✅ full label |
| Payroll | `payroll-generate`, `attendances` | ✅ full label |
| **Pengecualian minor** | `utilitas/notifications` (textarea broadcast — tambah label "Isi Pengumuman"), `material/upload-material` (dropzone — tambah keterangan) | ⏳ ditambahkan bertahap |

---

## 7. Acuan File
- Komponen: `resources/views/components/form-card.blade.php`, `components/combobox.blade.php`
- Dokumen terkait: `docs/STANDAR-INPUT-DETAIL.md`, `docs/AUDIT-COMBOBOX.md`, `docs/UAT-CHECKLIST-V2.md`
