238 lines
8.4 KiB
Dart
238 lines
8.4 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import 'package:firebase_auth/firebase_auth.dart';
|
|
import 'package:firebase_core/firebase_core.dart';
|
|
import 'package:firebase_database/firebase_database.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'main_screen.dart';
|
|
|
|
class ResultScreen extends StatelessWidget {
|
|
final Map<String, dynamic> activityData;
|
|
|
|
const ResultScreen({Key? key, required this.activityData}) : super(key: key);
|
|
|
|
Future<void> _saveActivityAndGoHome(BuildContext context) async {
|
|
try {
|
|
final user = FirebaseAuth.instance.currentUser;
|
|
if (user == null) throw Exception("User belum login");
|
|
|
|
final docRef = FirebaseFirestore.instance.collection('activities').doc(); // buat ID manual
|
|
await docRef.set({
|
|
'data': {
|
|
'userId': user.uid,
|
|
'type': activityData['type'] ?? 'non-lintasan',
|
|
'jarak': activityData['jarak'] ?? activityData['distance'] ?? 0.0,
|
|
'satuan': activityData['satuan'] ?? 'M',
|
|
'putaran': activityData['putaran'] ?? 0,
|
|
'duration': activityData['duration'],
|
|
'startTime': activityData['startTime'],
|
|
'timestamp': FieldValue.serverTimestamp(),
|
|
}
|
|
});
|
|
|
|
|
|
// AMBIL LAPS DARI RTDB DAN SIMPAN JUGA
|
|
final rtdb = FirebaseDatabase.instanceFor(
|
|
app: Firebase.app(),
|
|
databaseURL: "https://ta-running-default-rtdb.asia-southeast1.firebasedatabase.app",
|
|
);
|
|
|
|
final lapsRef = rtdb.ref("activities/${activityData['uidTag']}/laps");
|
|
final lapSnap = await lapsRef.get();
|
|
final lapData = lapSnap.value;
|
|
|
|
if (lapData != null && lapData is Map) {
|
|
await docRef.update({
|
|
'data.laps': lapData,
|
|
});
|
|
print("✅ Laps disimpan ke Firestore.");
|
|
} else {
|
|
print("⚠️ Laps tidak ditemukan di RTDB.");
|
|
}
|
|
|
|
|
|
Navigator.pushAndRemoveUntil(
|
|
context,
|
|
MaterialPageRoute(builder: (_) => const MainScreen()),
|
|
(route) => false,
|
|
);
|
|
} catch (e) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
SnackBar(content: Text('Gagal menyimpan aktivitas: $e')),
|
|
);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final type = activityData['type'] ?? 'Tidak diketahui';
|
|
final rawJarak = activityData['jarak'] ?? activityData['distance'] ?? 0.0;
|
|
final satuan = activityData['satuan'] ?? 'M';
|
|
final jarak = satuan == 'M' ? rawJarak / 1000.0 : rawJarak;
|
|
final putaran = activityData['putaran'] ?? '-';
|
|
|
|
int? startTimeMillis = activityData['startTime'];
|
|
DateTime? startTime;
|
|
if (startTimeMillis != null) {
|
|
startTime = DateTime.fromMillisecondsSinceEpoch(startTimeMillis);
|
|
}
|
|
|
|
int? durationMillis = activityData['duration'];
|
|
String durationFormatted = '-';
|
|
if (durationMillis != null) {
|
|
final dur = Duration(milliseconds: durationMillis);
|
|
durationFormatted = dur.toString().split('.').first.padLeft(8, "0");
|
|
} else if (startTime != null) {
|
|
final dur = DateTime.now().difference(startTime);
|
|
durationFormatted = dur.toString().split('.').first.padLeft(8, "0");
|
|
}
|
|
|
|
// ✅ Format pace jika tersedia
|
|
String? paceFormatted;
|
|
if (type == 'non-lintasan' && activityData['pace_sec_per_km'] != null) {
|
|
final paceSec = (activityData['pace_sec_per_km'] as num).toDouble();
|
|
final paceMin = paceSec ~/ 60;
|
|
final paceSecRem = (paceSec % 60).round();
|
|
paceFormatted = '$paceMin:${paceSecRem.toString().padLeft(2, '0')} /km';
|
|
}
|
|
|
|
String getRunPeriodLabel(DateTime time) {
|
|
final hour = time.hour;
|
|
if (hour >= 6 && hour <= 10) {
|
|
return 'Berlari Pagi';
|
|
} else if (hour >= 11 && hour <= 14) {
|
|
return 'Berlari Siang';
|
|
} else if (hour >= 15 && hour <= 17) {
|
|
return 'Berlari Sore';
|
|
} else {
|
|
return 'Berlari Malam';
|
|
}
|
|
}
|
|
|
|
|
|
return Scaffold(
|
|
backgroundColor: Colors.white,
|
|
body: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 40),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
const Text(
|
|
'Selamat! Kamu telah menyelesaikan\naktivitas',
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(fontSize: 26, fontWeight: FontWeight.w700),
|
|
),
|
|
const SizedBox(height: 30),
|
|
Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 24),
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
colors: [Colors.blueAccent.shade200, Colors.blue.shade400],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
borderRadius: BorderRadius.circular(20),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.4),
|
|
offset: const Offset(0, 4),
|
|
blurRadius: 8,
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
children: [
|
|
Text(
|
|
getRunPeriodLabel(startTime ?? DateTime.now()),
|
|
style: const TextStyle(
|
|
fontSize: 30,
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
if (type == 'lintasan') ...[
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
_infoItem('${jarak.toStringAsFixed(2)} KM', 'Jarak'),
|
|
_infoItem(durationFormatted, 'Durasi'),
|
|
],
|
|
),
|
|
const SizedBox(height: 16),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
_infoItem('$putaran', 'Putaran'),
|
|
_infoItem('Lintasan', 'Jenis Aktivitas'),
|
|
],
|
|
),
|
|
] else ...[
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
_infoItem('${jarak.toStringAsFixed(2)} KM', 'Jarak'),
|
|
_infoItem(durationFormatted, 'Durasi'),
|
|
],
|
|
),
|
|
if (paceFormatted != null) ...[
|
|
const SizedBox(height: 16),
|
|
_infoItem(paceFormatted!, 'Pace'),
|
|
],
|
|
const SizedBox(height: 16),
|
|
Text(
|
|
'Jenis Aktivitas\nNon-Lintasan',
|
|
textAlign: TextAlign.center,
|
|
style: const TextStyle(color: Colors.white, fontSize: 15),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 40),
|
|
SizedBox(
|
|
width: double.infinity,
|
|
child: ElevatedButton(
|
|
onPressed: () => _saveActivityAndGoHome(context),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Colors.blue,
|
|
padding: const EdgeInsets.symmetric(vertical: 14),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(24),
|
|
),
|
|
),
|
|
child: const Text(
|
|
'Kembali ke Beranda',
|
|
style: TextStyle(fontSize: 16, color: Colors.white),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _infoItem(String value, String label) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
value,
|
|
style: const TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 16,
|
|
),
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
label,
|
|
style: const TextStyle(color: Colors.white70, fontSize: 12),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|