ADD ALOT OF POLISHING AND UPDATES...

This commit is contained in:
Wowieee4
2026-05-26 05:52:12 +07:00
parent 2e3ecdf1d1
commit b8ad8df993
53 changed files with 3194 additions and 3860 deletions
@@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import '../../app/injection_container.dart';
import '../../core/errors/friendly_error.dart';
import '../../core/network/api_client.dart';
import '../../core/services/haptic_service.dart';
import '../../core/services/tts_service.dart';
@@ -94,15 +95,17 @@ class _SosScreenState extends State<SosScreen>
// ── API Calls ─────────────────────────────────────────────────────────────
Future<Position?> _getPosition() async {
try {
final permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) return null;
return await Geolocator.getCurrentPosition()
.timeout(const Duration(seconds: 6));
} catch (_) {
return null;
}
return runFriendly<Position>(
() async {
final permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied ||
permission == LocationPermission.deniedForever) return null;
return await Geolocator.getCurrentPosition()
.timeout(const Duration(seconds: 6));
},
onError: (_) {},
fallback: 'Lokasi belum bisa dibaca.',
);
}
Future<void> _loadHistory() async {
@@ -110,26 +113,24 @@ class _SosScreenState extends State<SosScreen>
_historyLoading = true;
_historyError = null;
});
try {
final res = await _api.get('/user/sos-events',
queryParameters: {'size': 10}).timeout(const Duration(seconds: 8));
final data = res.data['data'];
final content = data is Map ? data['content'] : null;
final items = content is List
? content
.whereType<Map>()
.map((e) => _SosEvent.fromMap(Map<String, dynamic>.from(e)))
.toList()
: <_SosEvent>[];
setState(() => _events = items);
} on DioException catch (e) {
final msg = e.response?.data?['message']?.toString();
setState(() => _historyError = msg ?? 'Tidak bisa memuat riwayat SOS.');
} catch (_) {
setState(() => _historyError = 'Tidak bisa memuat riwayat SOS.');
} finally {
if (mounted) setState(() => _historyLoading = false);
}
await runFriendlyAction(
() async {
final res = await _api.get('/user/sos-events',
queryParameters: {'size': 10}).timeout(const Duration(seconds: 8));
final data = res.data['data'];
final content = data is Map ? data['content'] : null;
final items = content is List
? content
.whereType<Map>()
.map((e) => _SosEvent.fromMap(Map<String, dynamic>.from(e)))
.toList()
: <_SosEvent>[];
setState(() => _events = items);
},
onError: (message) => setState(() => _historyError = message),
fallback: 'Tidak bisa memuat riwayat SOS.',
);
if (mounted) setState(() => _historyLoading = false);
}
Future<void> _confirmAndSend() async {
@@ -178,25 +179,23 @@ class _SosScreenState extends State<SosScreen>
Future<void> _sendSos() async {
setState(() => _sending = true);
try {
final pos = await _getPosition();
await _api.post('/user/sos', data: {
'triggerType': 'BUTTON',
'lat': pos?.latitude,
'lng': pos?.longitude,
});
await sl<HapticService>().sosTriggered();
sl<TtsService>().speak('SOS terkirim ke Guardian.');
_snack('SOS berhasil dikirim! Guardian sudah diberitahu.');
await _loadHistory();
} on DioException catch (e) {
final msg = e.response?.data?['message']?.toString() ?? 'Gagal kirim SOS';
_snack(msg);
} catch (e) {
_snack('Gagal kirim SOS: $e');
} finally {
if (mounted) setState(() => _sending = false);
}
await runFriendlyAction(
() async {
final pos = await _getPosition();
await _api.post('/user/sos', data: {
'triggerType': 'BUTTON',
'lat': pos?.latitude,
'lng': pos?.longitude,
});
await sl<HapticService>().sosTriggered();
sl<TtsService>().speak('SOS terkirim ke Guardian.');
_snack('SOS berhasil dikirim! Guardian sudah diberitahu.');
await _loadHistory();
},
onError: _snack,
fallback: 'Gagal kirim SOS. Coba lagi sebentar.',
);
if (mounted) setState(() => _sending = false);
}
// ── Build ──────────────────────────────────────────────────────────────────