129 lines
3.8 KiB
PHP
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',
|
|
};
|
|
}
|