import 'dart:convert'; import 'package:http/http.dart' as http; /// Service for myQuran.com v3 Sholat API. /// Provides Kemenag-accurate prayer times for Indonesian cities. /// /// Ported directly from the jamshalat-diary project. class MyQuranSholatService { static const String _baseUrl = 'https://api.myquran.com/v3/sholat'; static final MyQuranSholatService instance = MyQuranSholatService._(); MyQuranSholatService._(); /// Search for a city/kabupaten by name. /// Returns list of {id, lokasi}. Future>> searchCity(String query) async { try { final response = await http.get( Uri.parse('$_baseUrl/kota/cari/$query'), ); if (response.statusCode == 200) { final data = json.decode(response.body); if (data['status'] == true) { return List>.from(data['data']); } } } catch (e) { // silent fallback — device is offline } return []; } /// Get prayer times for today. /// [cityId] = myQuran city ID (hash string) /// Returns map: {tanggal, imsak, subuh, terbit, dhuha, dzuhur, ashar, maghrib, isya} Future?> getDailySchedule(String cityId) async { try { final response = await http.get(Uri.parse('$_baseUrl/jadwal/$cityId/today')); if (response.statusCode == 200) { final data = json.decode(response.body); if (data['status'] == true) { final jadwalMap = data['data']['jadwal'] as Map; if (jadwalMap.isNotEmpty) { final firstKey = jadwalMap.keys.first; final jadwal = jadwalMap[firstKey]; if (jadwal != null) { final result = Map.from(jadwal.map((k, v) => MapEntry(k.toString(), v.toString()))); result['date'] = firstKey; return result; } } } } } catch (e) { // silent fallback } return null; } /// Get monthly prayer schedule (bulk fetch for offline caching). /// [month] = 'yyyy-MM' format (e.g., '2024-03') /// Returns map of date → jadwal. Future>> getMonthlySchedule( String cityId, String month) async { try { final response = await http.get( Uri.parse('$_baseUrl/jadwal/$cityId/$month'), ); if (response.statusCode == 200) { final data = json.decode(response.body); if (data['status'] == true) { final jadwalMap = data['data']['jadwal'] as Map; final result = >{}; for (final entry in jadwalMap.entries) { result[entry.key] = Map.from( (entry.value as Map).map( (k, v) => MapEntry(k.toString(), v.toString())), ); } return result; } } } catch (e) { // silent fallback } return {}; } /// Get city info (kabko, prov) from a jadwal response. Future?> getCityInfo(String cityId) async { final today = DateTime.now().toIso8601String().substring(0, 10); try { final response = await http.get( Uri.parse('$_baseUrl/jadwal/$cityId/$today'), ); if (response.statusCode == 200) { final data = json.decode(response.body); if (data['status'] == true) { return { 'kabko': data['data']['kabko']?.toString() ?? '', 'prov': data['data']['prov']?.toString() ?? '', }; } } } catch (e) { // silent fallback } return null; } }