# PANDUAN IMPLEMENTASI FITUR PENDAFTARAN SEKOLAH
## Berdasarkan Struktur Existing FLS3N 2025

---

## A. REKOMENDASI TEKNIS

### 1. Pilihan Pendekatan

#### Opsi A: Tabel Sekolah Terpisah (RECOMMENDED)
**Kelebihan:**
- ✓ Normalisasi database
- ✓ Menghindari duplikasi nama sekolah
- ✓ Mudah update informasi sekolah terpusat
- ✓ Bisa tambah field: kabupaten, alamat, kategori, dll
- ✓ Audit trail perubahan data sekolah

**Kekurangan:**
- ✗ Perlu migration dari data existing
- ✗ Query lebih kompleks (JOIN)

#### Opsi B: Keep Simple (Current Approach)
**Kelebihan:**
- ✓ Tidak perlu perubahan database
- ✓ Fleksibel untuk PKBM/Non Formal

**Kekurangan:**
- ✗ Bisa ada duplikasi nama sekolah
- ✗ NPSN bukan unique identifier

---

## B. IMPLEMENTASI OPSI A: TABEL SEKOLAH TERPISAH

### 1. SQL untuk Membuat Struktur

```sql
-- 1. Buat tabel master_sekolah
CREATE TABLE master_sekolah (
    ID INT PRIMARY KEY AUTO_INCREMENT,
    Nama_Sekolah VARCHAR(255) NOT NULL,
    NPSN VARCHAR(50) UNIQUE NOT NULL,
    Kabupaten_Kota VARCHAR(100),
    Kategori ENUM('NEGERI', 'SWASTA', 'PKBM', 'NON_FORMAL') DEFAULT 'NEGERI',
    Alamat TEXT,
    Tipe_Sekolah ENUM('SMP', 'SMA', 'SMK', 'LAINNYA') DEFAULT 'SMA',
    Status ENUM('AKTIF', 'NONAKTIF') DEFAULT 'AKTIF',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    UNIQUE KEY unique_sekolah (Nama_Sekolah, Kabupaten_Kota),
    INDEX idx_npsn (NPSN),
    INDEX idx_kabupaten (Kabupaten_Kota)
);

-- 2. Modifikasi tabel domisilikota untuk foreign key
ALTER TABLE domisilikota 
ADD COLUMN Sekolah_ID INT,
ADD FOREIGN KEY (Sekolah_ID) REFERENCES master_sekolah(ID) ON DELETE RESTRICT;

-- 3. Lakukan untuk semua tabel peserta
ALTER TABLE domisilikabupaten 
ADD COLUMN Sekolah_ID INT,
ADD FOREIGN KEY (Sekolah_ID) REFERENCES master_sekolah(ID) ON DELETE RESTRICT;

ALTER TABLE domisilikabupaten2 
ADD COLUMN Sekolah_ID INT,
ADD FOREIGN KEY (Sekolah_ID) REFERENCES master_sekolah(ID) ON DELETE RESTRICT;
```

### 2. Admin UI: Kelola Sekolah

**File**: `admin/admin_dashboard/admin_kelola_sekolah/index.php`

**Struktur Halaman:**

```
Header: "Kelola Sekolah"
├─ Buttons:
│  ├─ "+ Tambah Sekolah"
│  ├─ "🗑 Hapus Sekunah"
│  └─ "📥 Import Sekolah"
│
├─ Filter & Search Bar:
│  ├─ Filter Kabupaten
│  ├─ Filter Kategori
│  ├─ Search: Nama Sekolah / NPSN
│  └─ Search Button
│
└─ Data Table:
   ├─ Kolom: Nama Sekolah, NPSN, Kabupaten, Kategori, Status, Aksi
   ├─ Pagination
   ├─ Action Buttons:
   │  ├─ Edit (modal form)
   │  ├─ Delete (confirm modal)
   │  └─ Toggle Status
   └─ Responsive Design
```

**Modal: Tambah/Edit Sekolah**

```html
Form Input:
├─ Nama Sekolah (text, required, UPPERCASE)
├─ NPSN (text, required, 10 digit numeric)
├─ Kabupaten/Kota (dropdown)
├─ Kategori (dropdown: NEGERI, SWASTA, PKBM, NON_FORMAL)
├─ Tipe Sekolah (dropdown: SMP, SMA, SMK, LAINNYA)
├─ Alamat (textarea)
├─ Status (radio: AKTIF/NONAKTIF)
└─ Buttons: Cancel, Simpan
```

**Modal: Import Sekolah**

```csv
Template Format (sekolah.csv):
Nama_Sekolah;NPSN;Kabupaten_Kota;Kategori;Tipe_Sekolah
SMA NEGERI 1 SEMARANG;20360001;Kabupaten Semarang;NEGERI;SMA
SMA KRISTEN 2;20360011;Kabupaten Semarang;SWASTA;SMA
PKBM MAJU;PKBM;Kota Salatiga;PKBM;LAINNYA
```

### 3. Form Pendaftaran: Integrasi Dropdown Sekolah

**File**: `cabang_lomba_kab/form-daftar/index.php` (Modified)

**Perubahan Bagian Sekolah:**

```html
<!-- BEFORE -->
<div class="col-md-6 mb-3">
    <label class="form-label">Nama Sekolah</label>
    <input type="text" class="form-control" name="nama_sekolah" required>
</div>

<!-- AFTER -->
<div class="col-md-6 mb-3">
    <label class="form-label">Nama Sekolah</label>
    <select class="form-select" name="sekolah_id" id="sekolahSelect" required>
        <option value="">Pilih Sekolah</option>
        <!-- Options dari database via AJAX -->
    </select>
</div>

<!-- Hidden inputs untuk nama & NPSN (auto-populated) -->
<input type="hidden" name="nama_sekolah" id="namaSekolahHidden">
<input type="hidden" name="npsn" id="npsn_hidden">
```

**JavaScript: Auto-populate NPSN**

```javascript
document.getElementById('sekolahSelect').addEventListener('change', function() {
    const sekolahId = this.value;
    
    if (!sekolahId) {
        document.getElementById('npsn_hidden').value = '';
        return;
    }
    
    // AJAX fetch ke endpoint yang return {npsn, nama_sekolah}
    fetch(`../../api/get_sekolah.php?id=${sekolahId}`)
        .then(res => res.json())
        .then(data => {
            document.getElementById('npsn_hidden').value = data.npsn;
            document.getElementById('namaSekolahHidden').value = data.nama_sekolah;
        });
});
```

---

## C. IMPLEMENTASI OPSI B: KEEP SIMPLE (No DB Changes)

### Hanya Tambahkan: Admin UI untuk Manage Sekolah

**Tanpa Foreign Key, hanya dokumentasi list sekolah yang valid:**

```php
// admin/admin_dashboard/admin_list_sekolah/index.php

// Baca dari query DISTINCT pada domisilikota, domisilikabupaten, domisilikabupaten2
$sql_sekolah_kota = "SELECT DISTINCT Nama_Sekolah, NPSN FROM domisilikota ORDER BY Nama_Sekolah";
$sql_sekolah_kab1 = "SELECT DISTINCT Nama_Sekolah, NPSN FROM domisilikabupaten ORDER BY Nama_Sekolah";
$sql_sekolah_kab2 = "SELECT DISTINCT Nama_Sekolah, NPSN FROM domisilikabupaten2 ORDER BY Nama_Sekolah";

// Merge dan display dalam satu tabel dengan kolom "Lokasi Terdaftar"
```

**Kelebihan**: Minimal changes, maximum compatibility
**Kekurangan**: Tidak ada enforced master data, bisa duplikasi

---

## D. FORM PENDAFTARAN SEKOLAH: STANDALONE

Jika ingin form pendaftaran **sekolah** terpisah (bukan siswa):

### Struktur Database Tambahan:

```sql
CREATE TABLE registrasi_sekolah (
    ID INT PRIMARY KEY AUTO_INCREMENT,
    Nama_Sekolah VARCHAR(255) NOT NULL,
    NPSN VARCHAR(50) NOT NULL,
    Email_Sekolah VARCHAR(100),
    Nama_Kontak VARCHAR(100),
    No_Kontak VARCHAR(20),
    Alamat TEXT,
    Kabupaten_Kota VARCHAR(100),
    Kategori ENUM('NEGERI', 'SWASTA', 'PKBM') DEFAULT 'NEGERI',
    Status ENUM('PENDING', 'APPROVED', 'REJECTED') DEFAULT 'PENDING',
    
    Catatan_Admin TEXT,
    Approved_By INT,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    
    INDEX idx_status (Status),
    INDEX idx_karena FOREIGN KEY (Approved_By) REFERENCES users(id)
);
```

### Flow:

```
1. Sekolah mengakses halaman "Daftar Sekolah"
2. Isi form: Nama Sekolah, NPSN, Email, Kontak, Alamat
3. Submit → record masuk ke registrasi_sekolah dengan status PENDING
4. Admin review di "Manajemen Pendaftaran Sekolah"
5. Admin approve/reject → status berubah
6. Jika approved → data di-move ke master_sekolah
7. Notifikasi email dikirim ke sekolah
```

### Form HTML Template:

```html
<div class="form-section">
    <h5 class="form-section-title">
        <i class="fas fa-school"></i> Informasi Sekolah
    </h5>
    
    <div class="row">
        <div class="col-md-6 mb-3">
            <label class="form-label">Nama Sekolah</label>
            <input type="text" class="form-control" name="nama_sekolah" 
                   pattern="[A-Z0-9\s/]+" 
                   oninput="this.value = this.value.toUpperCase()"
                   required>
        </div>
        
        <div class="col-md-6 mb-3">
            <label class="form-label">NPSN Sekolah</label>
            <input type="text" class="form-control" name="npsn" 
                   pattern="[0-9]{8}|PKBM"
                   oninput="this.value = this.value.toUpperCase()"
                   required>
        </div>
    </div>
    
    <!-- + 6 field lainnya (email, kontak, alamat, kabupaten, kategori) -->
</div>
```

---

## E. MAPPING DARI EXISTING STRUKTUR

### File yang Bisa Dijadikan Template:

| Feature | Existing File | Purpose |
|---------|---------------|---------|
| Admin CRUD | `admin/admin_dashboard/admin_kelola_peserta/index.php` | Copy structure untuk CRUD sekolah |
| Form Responsive | `cabang_lomba_kab/form-daftar/index.php` | Copy styling & validation logic |
| Modal Dialog | Ada di kelola_peserta | Use for edit/delete confirmation |
| Import CSV | Ada di kelola_peserta | Adapt untuk import sekolah |
| Validation | `admin/config.php` | Extend sanitizeInput function |
| Color Scheme | `cabang_lomba_kab/form-daftar/index.php` | Keep consistent gradient |

---

## F. RECOMMENDED IMPLEMENTATION PATH

### Week 1: Foundation
- [ ] Database: Create `master_sekolah` table
- [ ] Config: Add `sanitizeSekolah()` function
- [ ] API: Create `api/get_sekolah.php` endpoint

### Week 2: Admin Interface
- [ ] Create folder: `admin/admin_dashboard/admin_kelola_sekolah/`
- [ ] Build CRUD operations (Create, Read, Update, Delete)
- [ ] Add import CSV functionality
- [ ] Add filter & search

### Week 3: Form Integration
- [ ] Modify form ke dropdown select (dari input text)
- [ ] Add AJAX auto-populate NPSN
- [ ] Test validation flow
- [ ] Mobile responsive check

### Week 4: Testing & Deployment
- [ ] Unit test setiap endpoint
- [ ] Integration test form submission
- [ ] SQL performance check (index optimization)
- [ ] User acceptance testing (UAT)

---

## G. VALIDATION CHECKLIST

```javascript
// Client-side validation untuk form sekolah
✓ Nama Sekolah: Not empty, UPPERCASE, max 255 char
✓ NPSN: Numeric (8 digit) OR "PKBM"
✓ Email: Valid email format
✓ Kontak: Valid phone number format (optional)
✓ Kabupaten: Must select one (dropdown)
✓ Kategori: Must select one (dropdown)

// Server-side validation
✓ NPSN unique check
✓ Nama Sekolah + Kabupaten composite unique
✓ Email unique (opsional)
✓ Input sanitization (stripslashes, htmlspecialchars)
✓ SQL injection prevention (prepared statements)
```

---

## H. SECURITY CONSIDERATIONS

```php
// 1. Input Sanitization
$nama_sekolah = sanitizeInput($_POST['nama_sekolah']);
$npsn = sanitizeInput($_POST['npsn']);

// 2. Prepared Statements (prevent SQL injection)
$stmt = $conn->prepare(
    "INSERT INTO master_sekolah (Nama_Sekolah, NPSN, Kabupaten_Kota) 
     VALUES (?, ?, ?)"
);
$stmt->bind_param("sss", $nama_sekolah, $npsn, $kabupaten);

// 3. Permission Check
requireRole("admin");  // Only admin access

// 4. CSRF Token (add to forms)
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">

// 5. Rate Limiting (prevent brute force)
// Implement pada import & batch operations
```

---

## I. QUICK START CODE SNIPPET

```php
// Tambahan di admin/config.php
function addSekolah($nama_sekolah, $npsn, $kabupaten_kota) {
    $conn = connectDB();
    
    // Cek duplikasi
    $stmt = $conn->prepare(
        "SELECT ID FROM master_sekolah 
         WHERE Nama_Sekolah = ? AND Kabupaten_Kota = ?"
    );
    $stmt->bind_param("ss", $nama_sekolah, $kabupaten_kota);
    $stmt->execute();
    
    if ($stmt->get_result()->num_rows > 0) {
        return ["success" => false, "msg" => "Sekolah sudah terdaftar"];
    }
    
    // Insert
    $stmt = $conn->prepare(
        "INSERT INTO master_sekolah (Nama_Sekolah, NPSN, Kabupaten_Kota) 
         VALUES (?, ?, ?)"
    );
    $stmt->bind_param("sss", $nama_sekolah, $npsn, $kabupaten_kota);
    
    if ($stmt->execute()) {
        return ["success" => true, "msg" => "Sekolah berhasil ditambahkan", "id" => $conn->insert_id];
    } else {
        return ["success" => false, "msg" => "Error: " . $conn->error];
    }
}
```

---

*Panduan ini dapat disesuaikan dengan kebutuhan spesifik project*
