136 lines
5.3 KiB
Dart
136 lines
5.3 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import 'package:firebase_auth/firebase_auth.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
class AllActivityScreen extends StatelessWidget {
|
|
const AllActivityScreen({super.key});
|
|
|
|
Future<Map<String, Map<String, double>>> fetchWeeklySummary() async {
|
|
final user = FirebaseAuth.instance.currentUser;
|
|
if (user == null) return {};
|
|
|
|
final snapshot = await FirebaseFirestore.instance.collection('activities').get();
|
|
final Map<String, Map<String, double>> weeklyData = {};
|
|
|
|
final allDays = ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu', 'Minggu'];
|
|
|
|
for (var doc in snapshot.docs) {
|
|
final data = doc.data()['data'];
|
|
if (data == null || data['userId'] != user.uid) continue;
|
|
|
|
final timestamp = (data['timestamp'] as Timestamp?)?.toDate();
|
|
if (timestamp == null) continue;
|
|
|
|
final weekStart = DateTime(timestamp.year, timestamp.month, timestamp.day)
|
|
.subtract(Duration(days: timestamp.weekday - 1));
|
|
final weekKey = DateFormat('dd MMM yyyy').format(weekStart);
|
|
|
|
final hari = DateFormat('EEEE', 'id_ID').format(timestamp);
|
|
final jarak = (data['jarak'] ?? 0).toDouble();
|
|
final satuan = data['satuan'] ?? 'M';
|
|
final jarakKm = satuan == 'M' ? jarak / 1000.0 : jarak;
|
|
|
|
weeklyData.putIfAbsent(weekKey, () => {
|
|
for (var day in allDays) day: 0.0
|
|
});
|
|
|
|
weeklyData[weekKey]![hari] = (weeklyData[weekKey]![hari] ?? 0) + jarakKm;
|
|
}
|
|
|
|
return weeklyData;
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: Colors.white,
|
|
appBar: AppBar(
|
|
title: const Text("View All Weeks", style: TextStyle(color: Colors.white),),
|
|
automaticallyImplyLeading: true,
|
|
backgroundColor: Colors.blueAccent,
|
|
iconTheme: const IconThemeData(color: Colors.white),
|
|
),
|
|
body: FutureBuilder<Map<String, Map<String, double>>>(
|
|
future: fetchWeeklySummary(),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
|
|
final data = snapshot.data ?? {};
|
|
if (data.isEmpty) {
|
|
return const Center(child: Text("Belum ada data aktivitas lari."));
|
|
}
|
|
|
|
final sortedWeeks = data.keys.toList()
|
|
..sort((a, b) => DateFormat('dd MMM yyyy').parse(b).compareTo(DateFormat('dd MMM yyyy').parse(a)));
|
|
|
|
return ListView.builder(
|
|
itemCount: sortedWeeks.length,
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
|
itemBuilder: (context, index) {
|
|
final week = sortedWeeks[index];
|
|
final daysData = data[week]!;
|
|
final totalKm = daysData.values.fold(0.0, (a, b) => a + b);
|
|
|
|
return Card(
|
|
color: Colors.white,
|
|
elevation: 3,
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
|
margin: const EdgeInsets.only(bottom: 16),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
const Icon(Icons.calendar_today, size: 20, color: Colors.blue),
|
|
const SizedBox(width: 8),
|
|
Text(
|
|
'Minggu dimulai: $week',
|
|
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 12),
|
|
Column(
|
|
children: daysData.entries.map((entry) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 2),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(entry.key, style: const TextStyle(fontSize: 14)),
|
|
Text('${entry.value.toStringAsFixed(2)} KM',
|
|
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500)),
|
|
],
|
|
),
|
|
);
|
|
}).toList(),
|
|
),
|
|
const Divider(height: 24, thickness: 1),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: [
|
|
const Icon(Icons.directions_run, size: 18, color: Colors.green),
|
|
const SizedBox(width: 6),
|
|
Text(
|
|
'Total: ${totalKm.toStringAsFixed(2)} KM',
|
|
style: const TextStyle(fontWeight: FontWeight.w600),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|