118 lines
3.7 KiB
Dart
118 lines
3.7 KiB
Dart
import 'dart:async';
|
|
import 'package:firebase_core/firebase_core.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:firebase_database/firebase_database.dart';
|
|
import 'result_screen.dart';
|
|
|
|
class MonitoringScreen extends StatefulWidget {
|
|
final String userId;
|
|
const MonitoringScreen({Key? key, required this.userId}) : super(key: key);
|
|
|
|
@override
|
|
State<MonitoringScreen> createState() => _MonitoringScreenState();
|
|
}
|
|
|
|
class _MonitoringScreenState extends State<MonitoringScreen> {
|
|
late DatabaseReference _activityRef;
|
|
StreamSubscription<DatabaseEvent>? _subscription;
|
|
bool _navigated = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
final db = FirebaseDatabase.instanceFor(
|
|
app: Firebase.app(),
|
|
databaseURL: "https://ta-running-default-rtdb.asia-southeast1.firebasedatabase.app",
|
|
);
|
|
_activityRef = db.ref("activities/${widget.userId}");
|
|
|
|
_subscription = _activityRef.onValue.listen((event) {
|
|
final raw = event.snapshot.value;
|
|
if (raw is Map) {
|
|
final data = Map<String, dynamic>.from(raw);
|
|
|
|
// ✅ Cek dan simpan startTime jika status == 'running' dan startTime belum ada
|
|
if (data['status'] == 'running' && data['startTime'] == null) {
|
|
final now = DateTime.now().toUtc(); // ambil SEKALI dalam UTC
|
|
final nowMillis = now.millisecondsSinceEpoch;
|
|
final nowIso = now.toIso8601String();
|
|
|
|
_activityRef.update({
|
|
'startTime': nowMillis,
|
|
'laps/lap_0/timestamp': nowIso,
|
|
});
|
|
|
|
print("⏱️ startTime dan lap_0 disimpan ke RTDB: $nowIso");
|
|
}
|
|
|
|
// ✅ Saat status 'done', proses navigasi dan simpan durasi
|
|
if (!_navigated && data['status'] == 'done') {
|
|
_navigated = true;
|
|
_subscription?.cancel();
|
|
|
|
int? dur;
|
|
|
|
if (data['startTime'] != null) {
|
|
final now = DateTime.now().millisecondsSinceEpoch;
|
|
dur = now - (data['startTime'] as int);
|
|
_activityRef.update({'duration': dur});
|
|
data['duration'] = dur;
|
|
}
|
|
|
|
final type = data['type'];
|
|
final rawJarak = data['jarak'];
|
|
final satuan = data['satuan'] ?? 'M';
|
|
|
|
double jarakKm = 0;
|
|
if (rawJarak != null) {
|
|
jarakKm = satuan == 'KM'
|
|
? (rawJarak as num).toDouble()
|
|
: (rawJarak as num).toDouble() / 1000.0;
|
|
}
|
|
|
|
if (type == 'non-lintasan' && jarakKm > 0 && dur != null) {
|
|
final durSec = dur / 1000.0;
|
|
final pacePerKmSec = durSec / jarakKm;
|
|
_activityRef.update({'pace_sec_per_km': pacePerKmSec});
|
|
data['pace_sec_per_km'] = pacePerKmSec;
|
|
}
|
|
|
|
data['uidTag'] = widget.userId;
|
|
|
|
Navigator.pushReplacement(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (_) => ResultScreen(activityData: data),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_subscription?.cancel();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return const Scaffold(
|
|
backgroundColor: Colors.white,
|
|
body: Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
CircularProgressIndicator(color: Colors.blueAccent),
|
|
SizedBox(height: 20),
|
|
Text(
|
|
'Aktivitas sedang berlangsung...',
|
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
} |