Files

129 lines
3.8 KiB
PHP

<?php
// ================================================================
// Helper Functions
// ================================================================
require_once __DIR__ . '/../config/database.php';
/**
* JSON response helper
*/
function jsonResponse(array $data, int $code = 200): void {
http_response_code($code);
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
/**
* Haversine formula: jarak antara dua koordinat (meter)
*/
function haversineDistance(float $lat1, float $lng1, float $lat2, float $lng2): float {
$R = 6371000; // radius bumi meter
$dLat = deg2rad($lat2 - $lat1);
$dLng = deg2rad($lng2 - $lng1);
$a = sin($dLat / 2) * sin($dLat / 2)
+ cos(deg2rad($lat1)) * cos(deg2rad($lat2))
* sin($dLng / 2) * sin($dLng / 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
return $R * $c;
}
/**
* Cari rumah ibadah terdekat dari koordinat
*/
function findNearestIbadah(float $lat, float $lng): ?array {
$db = getDB();
$rows = $db->query("SELECT id, nama, jenis, lat, lng, radius FROM rumah_ibadah")->fetchAll();
$best = null;
$minDist = PHP_FLOAT_MAX;
foreach ($rows as $row) {
$dist = haversineDistance($lat, $lng, (float)$row['lat'], (float)$row['lng']);
if ($dist <= (float)$row['radius'] && $dist < $minDist) {
$minDist = $dist;
$best = array_merge($row, ['jarak' => round($dist, 2)]);
}
}
// Jika tidak ada dalam radius, cari yang paling dekat saja
if ($best === null && !empty($rows)) {
foreach ($rows as $row) {
$dist = haversineDistance($lat, $lng, (float)$row['lat'], (float)$row['lng']);
if ($dist < $minDist) {
$minDist = $dist;
$best = array_merge($row, ['jarak' => round($dist, 2), 'di_luar_radius' => true]);
}
}
}
return $best;
}
/**
* Sanitize string input
*/
function sanitize(string $val): string {
return trim(htmlspecialchars($val, ENT_QUOTES, 'UTF-8'));
}
/**
* Format radius display
*/
function formatRadius(int $meter): string {
return $meter >= 1000 ? number_format($meter / 1000, 1) . ' km' : $meter . ' m';
}
/**
* Format tanggal Indonesia
*/
function formatTanggal(?string $date): string {
if (!$date) return '-';
$ts = strtotime($date);
$bulan = ['','Jan','Feb','Mar','Apr','Mei','Jun','Jul','Agt','Sep','Okt','Nov','Des'];
return date('d', $ts) . ' ' . $bulan[(int)date('n', $ts)] . ' ' . date('Y', $ts);
}
/**
* Handle file upload
*/
function handleUpload(array $file, string $prefix = 'bukti'): ?string {
if ($file['error'] !== UPLOAD_ERR_OK) return null;
if ($file['size'] > UPLOAD_MAX_SIZE) return null;
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if (!in_array($ext, UPLOAD_ALLOWED)) return null;
if (!is_dir(UPLOAD_DIR)) mkdir(UPLOAD_DIR, 0755, true);
$filename = $prefix . '_' . date('Ymd_His') . '_' . uniqid() . '.' . $ext;
$dest = UPLOAD_DIR . $filename;
if (move_uploaded_file($file['tmp_name'], $dest)) return $filename;
return null;
}
/**
* Emoji dan label untuk jenis ibadah
*/
function ibadahEmoji(string $jenis): string {
$map = [
'Masjid' => '🕌',
'Musholla' => '🕌',
'Gereja' => '⛪',
'Katolik' => '⛪',
'Pura' => '🛕',
'Vihara' => '🛕',
'Klenteng' => '⛩️',
'Lainnya' => '🙏',
];
return $map[$jenis] ?? '🏛️';
}
/**
* Color untuk marker berdasarkan status
*/
function statusColor(string $status): string {
return match($status) {
'sudah' => '#22c55e',
'menunggu' => '#f59e0b',
default => '#ef4444',
};
}