# 📋 Fungsi JavaScript untuk Tab "Penilaian Individu"

## 🎯 Fungsi Utama (Main Functions)

### 1. **displayTabContent(tabId)** 
**Lokasi:** Line 5123-5193  
**Fungsi:** Menampilkan tab yang dipilih termasuk tab "Penilaian Individu"

**Kode Relevan:**
```javascript
function displayTabContent(tabId) {
    // 1. Sembunyikan semua tab
    document.querySelectorAll('.tab-content').forEach(tab => {
        tab.style.display = 'none';
    });

    // 2. Hapus class active dari semua tombol tab
    document.querySelectorAll('.tab-button').forEach(btn => {
        btn.classList.remove('active');
    });

    // 3. Tampilkan tab yang dipilih
    const selectedTab = document.getElementById(tabId);
    if (selectedTab) {
        selectedTab.style.display = 'block';
    }

    // 4. Tambahkan class active pada tombol yang diklik
    const activeButton = document.querySelector(`[data-tab="${tabId}"]`);
    if (activeButton) {
        activeButton.classList.add('active');
    }

    // 5. Update currentTab variable untuk tracking
    currentTab = tabId;

    // 6. Special handling untuk tab individu ⭐
    if (tabId === 'individualTab') {
        loadStudentIndividualList();  // ← Ini yang dipanggil!
    }

    // 8. Hitung statistik
    calculateStatistics();
}
```

**Trigger:** Ketika user klik tombol tab "Penilaian Individu"
```html
<button class="tab-button" data-tab="individualTab" 
        onclick="displayTabContent('individualTab')">
    <i class="fas fa-user-check"></i>
    Penilaian Individu
</button>
```

---

## 📊 Fungsi-Fungsi Tampilan (Display Functions)

### 2. **loadStudentIndividualList()**
**Lokasi:** Line 3888-3948  
**Fungsi:** Memuat dan menampilkan daftar siswa dalam grid

**Deskripsi:**
- Mengumpulkan semua siswa dari semua kelompok (ketua + anggota)
- Menampilkan dalam format grid dengan kartu (card) yang bisa diklik
- Setiap kartu menampilkan: nama, role, grup, email, avatar inisial

**HTML Elements yang Diisi:**
- `document.getElementById('studentIndividualList')` - Container untuk daftar siswa
- `document.getElementById('emptyStudentList')` - Empty state message

**Kode Relevan:**
```javascript
function loadStudentIndividualList() {
    console.log("projectGroups (INDIVIDU):", projectGroups);
    const container = document.getElementById('studentIndividualList');
    const emptyState = document.getElementById('emptyStudentList');
    
    // Collect semua siswa dari semua kelompok
    let allStudents = [];
    projectGroups.forEach((group, groupIndex) => {
        // Tambah ketua
        if (group.leader) {
            allStudents.push({
                name: group.leader,
                group: group.name,
                groupId: group.id,
                role: 'Ketua',
                initial: group.leader.charAt(0).toUpperCase()
            });
        }
        
        // Tambah anggota
        if (group.members && group.members.length > 0) {
            group.members.forEach(member => {
                const memberName = typeof member === 'string' ? member : (member.full_name || member.name);
                allStudents.push({
                    name: memberName,
                    email: typeof member === 'object' ? member.email : '',
                    group: group.name,
                    groupId: group.id,
                    role: 'Anggota',
                    initial: memberName.charAt(0).toUpperCase()
                });
            });
        }
    });
    
    // ... render ke HTML
}
```

**Data yang Digunakan:**
- `projectGroups` - Global variable berisi semua kelompok proyek
- `group.leader` - Nama ketua kelompok
- `group.members` - Array anggota kelompok

---

### 3. **openStudentDetail(studentName, groupName)**
**Lokasi:** Line 3992-4085  
**Fungsi:** Membuka modal detail siswa dengan semua informasinya

**Deskripsi:**
- Update header modal dengan informasi siswa
- Load feedback yang sudah tersimpan
- Display file dari semua fase (rancangan, pelaksanaan, hasil, laporan)
- Populate textarea dengan feedback keseluruhan

**HTML Elements yang Diupdate:**
- `document.getElementById('detailStudentName')` - Nama siswa
- `document.getElementById('detailStudentInitial')` - Inisial (avatar)
- `document.getElementById('detailStudentGroup')` - Nama kelompok
- `document.getElementById('detailStudentEmail')` - Email siswa
- `document.getElementById('detailStudentFiles')` - Daftar file
- `document.getElementById('feedbackInput')` - Textarea feedback keseluruhan
- `document.getElementById('studentDetailModal')` - Modal dialog

**Kode Relevan:**
```javascript
function openStudentDetail(studentName, groupName) {
    currentStudentDetail = { studentName, groupName };
    
    // Update header
    document.getElementById('detailStudentName').textContent = studentName;
    document.getElementById('detailStudentInitial').textContent = studentName.charAt(0).toUpperCase();
    document.getElementById('detailStudentGroup').textContent = `Kelompok: ${groupName}`;
    
    // Load saved individual reflections
    loadAndDisplaySavedReflection(studentName);  // ← Load data tersimpan

    // Populate overall feedback textarea dari cache
    if (Array.isArray(window.reflectionData)) {
        const student = window.reflectionData.find(s =>
            (s.student_name || '').trim().toLowerCase() === (studentName || '').trim().toLowerCase()
        );
        if (student) {
            const fbEl = document.getElementById('feedbackInput');
            if (fbEl) fbEl.value = student.comment || '';
        }
    }
    
    // Load files dari semua fase
    let allFiles = [];
    if (group?.submissions?.[1]) {  // Rancangan
        allFiles = allFiles.concat(
            group.submissions[1].files.map(f => ({ ...f, phase: 'Rancangan' }))
        );
    }
    // ... dan seterusnya untuk phase 2, 3, 4
    
    // Show modal
    document.getElementById('studentDetailModal').style.display = 'block';
}
```

**Trigger:** Ketika user klik kartu siswa dalam grid
```html
onclick="openStudentDetail('${student.name.replace(/'/g, "\\'")}', '${student.group}')"
```

---

### 4. **loadAndDisplaySavedReflection(studentName)**
**Lokasi:** Line 4207-4280  
**Fungsi:** Load data refleksi siswa yang sudah tersimpan dari database

**Deskripsi:**
- Fetch data dari API `get-individual-reflections.php`
- Populate field "Nilai" dan "Komentar"
- Display file yang sudah terupload (refleksi dan analisis)

**HTML Elements yang Diupdate:**
- `document.getElementById('reflectionAnalysisScore')` - Input nilai
- `document.getElementById('reflectionAnalysisComment')` - Textarea komentar
- `document.getElementById('fileSummary')` - Summary file tersimpan

**API Endpoint:**
```
GET /TA/api/assessment/get-individual-reflections.php?project_id={projectId}
```

**Kode Relevan:**
```javascript
async function loadAndDisplaySavedReflection(studentName) {
    try {
        // Prefer cached data dari window.reflectionData
        let reflections = Array.isArray(window.reflectionData) ? window.reflectionData : null;

        if (!reflections) {
            // Fallback ke fetch jika cache tidak ada
            const url = `/TA/api/assessment/get-individual-reflections.php?project_id=${currentProjectId}`;
            const response = await fetch(url, { method: 'GET', credentials: 'include' });
            if (response.ok) {
                const result = await response.json();
                reflections = result && result.data ? result.data : [];
                if (Array.isArray(reflections)) window.reflectionData = reflections;
            }
        }

        // Cari siswa yang sesuai
        if (Array.isArray(reflections) && reflections.length > 0) {
            const studentReflection = reflections.find(r => r.student_name === studentName);

            if (studentReflection) {
                // Populate form fields
                const scoreInput = document.getElementById('reflectionAnalysisScore');
                const commentInput = document.getElementById('reflectionAnalysisComment');

                if (scoreInput) scoreInput.value = studentReflection.score || '';
                if (commentInput) commentInput.value = studentReflection.feedback || studentReflection.comment || '';

                // Display file summary
                displaySavedReflectionFiles(studentReflection);
            }
        }
    } catch (error) {
        console.warn('Error loading saved reflections:', error);
    }
}
```

---

### 5. **displaySavedReflectionFiles(reflection)**
**Lokasi:** Line 4283-...  
**Fungsi:** Menampilkan file yang sudah terupload (refleksi & analisis)

**HTML Elements yang Diupdate:**
- `document.getElementById('fileSummary')` - Container untuk file yang tersimpan

**Data yang Ditampilkan:**
- `reflection.reflection_path` - File refleksi
- `reflection.analysis_path` - File analisis
- `reflection.assessed_by_name` - Nama guru yang menilai
- `reflection.assessed_at` - Tanggal penilaian

---

### 6. **loadIndividualReflectionsData()**
**Lokasi:** Line 3962-3986  
**Fungsi:** Load semua data refleksi dari API (dipanggil saat load list siswa)

**API Endpoint:**
```
GET /TA/api/assessment/get-individual-reflections.php?project_id={projectId}
```

**Global Variables yang Disimpan:**
- `window.reflectionData` - Array semua refleksi siswa
- `individualReflectionsMap` - Map refleksi untuk backward compatibility

**Kode Relevan:**
```javascript
async function loadIndividualReflectionsData() {
    try {
        const url = `/TA/api/assessment/get-individual-reflections.php?project_id=${currentProjectId}`;
        const response = await fetch(url, { method: 'GET', credentials: 'include' });

        if (response.ok) {
            const result = await response.json();

            if (result && result.data) {
                individualReflectionsMap = {};
                result.data.forEach(reflection => {
                    if (reflection && reflection.student_id) 
                        individualReflectionsMap[reflection.student_id] = reflection;
                });

                // Save to global so click handlers can use it
                window.reflectionData = result.data;

                console.log('Individual reflections loaded (map):', individualReflectionsMap);
                console.log('Individual reflections saved to window.reflectionData');
            }
        }
    } catch (error) {
        console.warn('Gagal load individual reflections:', error);
    }
}
```

---

## 💾 Fungsi Penyimpanan (Save Functions)

### 7. **saveStudentFeedback()**
**Lokasi:** Line 4091-4141  
**Fungsi:** Simpan feedback dan nilai untuk siswa

**API Endpoint:**
```
POST /TA/api/assessment/save-individual-feedback.php
```

**Data yang Dikirim:**
- `project_id` - ID proyek
- `student_name` - Nama siswa
- `group_name` - Nama kelompok
- `feedback` - Feedback keseluruhan
- `score` - Nilai (0-100) dari refleksi & analisis

**Kode Relevan:**
```javascript
function saveStudentFeedback() {
    const feedback = document.getElementById('feedbackInput').value;
    
    if (!currentStudentDetail) {
        alert('Data siswa tidak ditemukan');
        return;
    }
    
    (async () => {
        try {
            const form = new URLSearchParams();
            const scoreInput = document.getElementById('reflectionAnalysisScore');
            const score = scoreInput ? scoreInput.value : '';
            
            form.append('project_id', currentProjectId);
            form.append('student_name', currentStudentDetail.studentName);
            form.append('group_name', currentStudentDetail.groupName);
            form.append('feedback', feedback || '');
            form.append('score', score);

            const resp = await fetch('../api/assessment/save-individual-feedback.php', {
                method: 'POST',
                credentials: 'include',
                body: form
            });

            const result = await resp.json();
            if (result && result.success) {
                alert(`✓ Feedback untuk ${currentStudentDetail.studentName} berhasil disimpan!`);
                closeStudentDetail();
            } else {
                alert('❌ Gagal menyimpan feedback: ' + (result && result.message ? result.message : 'Unknown'));
            }
        } catch (err) {
            console.error('saveStudentFeedback error', err);
            alert('❌ Terjadi kesalahan saat menyimpan feedback: ' + (err.message || err));
        }
    })();
}
```

**Trigger:** Ketika user klik tombol "Simpan Feedback"

---

### 8. **closeStudentDetail()**
**Lokasi:** Line 4086-4089  
**Fungsi:** Menutup modal detail siswa

**Kode:**
```javascript
function closeStudentDetail() {
    document.getElementById('studentDetailModal').style.display = 'none';
    currentStudentDetail = null;
}
```

**Trigger:** Ketika user klik "Batal" atau tombol X

---

## 📥 Fungsi Download (Export Functions)

### 9. **downloadIndividu()**
**Lokasi:** Line 3247-3257  
**Fungsi:** Download laporan individual siswa (Excel/PDF)

**API Endpoint:**
```
GET /TA/api/export/export-individual.php?project_id={projectId}
```

**Kode:**
```javascript
function downloadIndividu() {
    const projectId = currentProjectId;
    if (!projectId) {
        alert('Project ID tidak tersedia. Muat ulang halaman atau periksa parameter URL.');
        return;
    }
    window.open(`../api/export/export-individual.php?project_id=${projectId}`, '_blank');
}
```

---

### 10. **downloadPertanyaanMendasar()**
**Lokasi:** Line 3272-3282  
**Fungsi:** Download rekap pertanyaan mendasar siswa

**API Endpoint:**
```
GET /TA/api/export/export-pertanyaan-mendasar.php?project_id={projectId}
```

---

### 11. **downloadRekapSemua()**
**Lokasi:** Line 3262-3271  
**Fungsi:** Download rekap laporan semua fase

**API Endpoint:**
```
GET /TA/api/export/export-all-phases.php?project_id={projectId}
```

---

## 🔗 HTML Elements Terkait

### Tab Button (Line 2488)
```html
<button class="tab-button" data-tab="individualTab" onclick="displayTabContent('individualTab')">
    <i class="fas fa-user-check" style="color: var(--sdgs-green);"></i>
    Penilaian Individu
</button>
```

### Tab Content Container (Line 2921)
```html
<div id="individualTab" class="tab-content" style="display: flex;">
    <!-- Assessment Panel -->
    <div class="assessment-panel">
        <!-- Download Buttons -->
        <button class="btn btn-warning btn-sm" onclick="downloadIndividu()">
            <i class="fas fa-user"></i> Download Laporan Individu
        </button>
        
        <!-- Student List Grid -->
        <div id="studentIndividualList" style="display: grid; ...">
            <!-- Akan diisi oleh loadStudentIndividualList() -->
        </div>
        
        <!-- Empty State -->
        <div id="emptyStudentList" style="display: none; ...">
            <p>Belum ada siswa terdaftar dalam proyek ini</p>
        </div>
    </div>
    
    <!-- Student Detail Modal -->
    <div id="studentDetailModal" style="display: none; ...">
        <!-- Modal Content -->
    </div>
</div>
```

---

## 🔄 Global Variables Penting

```javascript
let currentProjectId;           // ID proyek yang sedang diedit
let projectGroups = [];         // Array semua kelompok proyek
let currentStudentDetail = null; // Siswa yang sedang dibuka modal-nya
let individualReflectionsMap = {};  // Map refleksi siswa
window.reflectionData = [];     // Array refleksi dari API (cache)
let currentTab = 'rubrikTab';   // Tab yang sedang aktif
```

---

## 📊 Alur Kerja (Workflow)

```
1. User Klik Tab "Penilaian Individu"
   ↓
2. displayTabContent('individualTab') dipanggil
   ↓
3. loadStudentIndividualList() dipanggil
   ↓
4. loadIndividualReflectionsData() dipanggil (fetch API)
   ↓
5. Grid siswa ditampilkan dari projectGroups
   ↓
6. User Klik Kartu Siswa
   ↓
7. openStudentDetail(studentName, groupName) dipanggil
   ↓
8. loadAndDisplaySavedReflection(studentName) dipanggil
   ↓
9. Modal dibuka dengan data siswa & feedback
   ↓
10. User Input Nilai & Komentar
    ↓
11. User Klik "Simpan Feedback"
    ↓
12. saveStudentFeedback() dipanggil
    ↓
13. POST ke save-individual-feedback.php
    ↓
14. Modal ditutup & data disimpan
```

---

## 📝 Summary

**Fungsi Utama untuk Tab "Penilaian Individu":**

| # | Fungsi | Lokasi | Tujuan |
|---|--------|--------|--------|
| 1 | `displayTabContent()` | Line 5123 | Display tab ketika diklik |
| 2 | `loadStudentIndividualList()` | Line 3888 | Tampilkan grid daftar siswa |
| 3 | `openStudentDetail()` | Line 3992 | Buka modal detail siswa |
| 4 | `loadAndDisplaySavedReflection()` | Line 4207 | Load data refleksi tersimpan |
| 5 | `displaySavedReflectionFiles()` | Line 4283 | Tampilkan file yang terupload |
| 6 | `loadIndividualReflectionsData()` | Line 3962 | Fetch semua refleksi dari API |
| 7 | `saveStudentFeedback()` | Line 4091 | Simpan feedback ke database |
| 8 | `closeStudentDetail()` | Line 4086 | Tutup modal |
| 9 | `downloadIndividu()` | Line 3247 | Download laporan individual |
| 10 | `downloadPertanyaanMendasar()` | Line 3272 | Download rekap pertanyaan |
| 11 | `downloadRekapSemua()` | Line 3262 | Download rekap semua |
