exec("SET time_zone = '+07:00'"); header('Content-Type: application/json'); if ($_SERVER['REQUEST_METHOD'] === 'POST') { $activity = isset($_POST['activity']) ? trim($_POST['activity']) : ''; $fotoData = isset($_POST['fotoData']) ? $_POST['fotoData'] : ''; $token = isset($_POST['token']) ? $_POST['token'] : ''; if (empty($activity) || empty($fotoData)) { echo json_encode(['status' => 'error', 'message' => 'Lengkapi data aktivitas dan foto.']); exit; } if (empty($token)) { echo json_encode(['status' => 'error', 'message' => 'Token tidak ditemukan.']); exit; } $usedTokensFile = __DIR__ . '/used_report_tokens.json'; $usedTokens = []; if (file_exists($usedTokensFile)) { $usedTokens = json_decode(file_get_contents($usedTokensFile), true) ?: []; } if (isset($usedTokens[$token])) { echo json_encode(['status' => 'error', 'message' => 'Token sudah digunakan.']); exit; } try { // Prepare image $fotoData = str_replace('data:image/jpeg;base64,', '', $fotoData); $fotoData = str_replace(' ', '+', $fotoData); $imgData = base64_decode($fotoData); if (!is_dir('uploads/history')) { mkdir('uploads/history', 0755, true); } $fileName = time() . '_' . uniqid() . '.jpg'; $filePath = 'uploads/history/' . $fileName; if (file_put_contents($filePath, $imgData)) { // 1. Insert ke schedule $stmt = $pdo->prepare("INSERT INTO schedule (date, kegiatan) VALUES (NOW(), ?)"); $stmt->execute([$activity]); $schedule_id = $pdo->lastInsertId(); // 2. Tentukan occupant_id (dengan validasi ketat) $occupant_id = null; // Cek dari parameter occ_id yang dikirim if (isset($_POST['occ_id']) && is_numeric($_POST['occ_id']) && (int) $_POST['occ_id'] > 0) { $checkOcc = $pdo->prepare("SELECT id_occupant FROM occupant WHERE id_occupant = ?"); $checkOcc->execute([(int) $_POST['occ_id']]); $foundOcc = $checkOcc->fetch(PDO::FETCH_ASSOC); if ($foundOcc) { $occupant_id = (int) $foundOcc['id_occupant']; } } // Fallback jika occ_id tidak valid atau tidak ditemukan if ($occupant_id === null) { $occStmt = $pdo->query("SELECT id_occupant FROM occupant ORDER BY id_occupant ASC LIMIT 1"); $occ = $occStmt->fetch(PDO::FETCH_ASSOC); if ($occ) { $occupant_id = (int) $occ['id_occupant']; } else { echo json_encode(['status' => 'error', 'message' => 'Tidak ada occupant terdaftar di sistem.']); exit; } } // 3. Insert ke history (simpan juga nama occupant agar nama tetap ada meskipun occupant dihapus) $getOccName = $pdo->prepare("SELECT name FROM occupant WHERE id_occupant = ?"); $getOccName->execute([$occupant_id]); $occName = $getOccName->fetchColumn(); $stmtHist = $pdo->prepare("INSERT INTO history (occupant_id, schedule_id, foto, occupant_name, is_read, is_starred, is_deleted) VALUES (?, ?, ?, ?, 0, 0, 0)"); $stmtHist->execute([$occupant_id, $schedule_id, $filePath, $occName]); // 4. Update Door Status to Locked & Send Notification $statusFile = __DIR__ . '/door_status.txt'; file_put_contents($statusFile, 'locked'); require_once 'PushHelper.php'; include_once 'notification_helper.php'; send_notification($pdo, 'mdi-door-closed-lock', 'Pintu Terkunci', 'Pintu Ruang FTM berhasil dikunci setelah Submit Report.', 'Pintu terkunci secara otomatis dari sistem laporan.', false); // 5. Signal ESP32 to proceed to SCR_MAIN $stateFile = __DIR__ . '/esp32_state.json'; if (file_exists($stateFile)) { $stateData = json_decode(file_get_contents($stateFile), true); if (is_array($stateData)) { $stateData['report_submitted'] = true; file_put_contents($stateFile, json_encode($stateData)); } } // 6. Mark token as used $usedTokens[$token] = time(); file_put_contents($usedTokensFile, json_encode($usedTokens, JSON_PRETTY_PRINT)); echo json_encode(['status' => 'success', 'message' => 'Data berhasil disimpan']); } else { echo json_encode(['status' => 'error', 'message' => 'Gagal menyimpan foto']); } } catch (PDOException $e) { echo json_encode(['status' => 'error', 'message' => 'Database error: ' . $e->getMessage()]); } } else { echo json_encode(['status' => 'error', 'message' => 'Invalid request']); } ?>