134 lines
3.4 KiB
Dart
134 lines
3.4 KiB
Dart
import 'dart:async';
|
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:firebase_auth/firebase_auth.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
class AnalisisController extends GetxController {
|
|
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
|
|
final FirebaseAuth _auth = FirebaseAuth.instance;
|
|
|
|
var monthlyData = <Map<String, dynamic>>[].obs;
|
|
var topCities = <Map<String, dynamic>>[].obs;
|
|
var selectedMonth = ''.obs;
|
|
|
|
StreamSubscription? _listenerRealtime;
|
|
|
|
// 🔥 simpan semua data di memory
|
|
List<QueryDocumentSnapshot<Map<String, dynamic>>> _allDocs = [];
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
selectedMonth.value = DateFormat('MMM').format(DateTime.now());
|
|
_listenRealtimeData();
|
|
}
|
|
|
|
@override
|
|
void onClose() {
|
|
_listenerRealtime?.cancel();
|
|
super.onClose();
|
|
}
|
|
|
|
void _listenRealtimeData() {
|
|
final user = _auth.currentUser;
|
|
if (user == null) return;
|
|
|
|
_listenerRealtime = _firestore
|
|
.collection('resis')
|
|
.where('store_id', isEqualTo: user.uid)
|
|
.snapshots()
|
|
.listen((snapshot) {
|
|
_allDocs = snapshot.docs;
|
|
_updateData();
|
|
});
|
|
}
|
|
|
|
void _updateData() {
|
|
final Map<String, int> pengirimanPerBulan = {};
|
|
final Map<String, Map<String, dynamic>> kotaSummary = {};
|
|
|
|
for (var doc in _allDocs) {
|
|
final data = doc.data();
|
|
|
|
if (data['created_at'] == null || data['kota'] == null) continue;
|
|
|
|
final createdAt =
|
|
(data['created_at'] as Timestamp).toDate().toLocal();
|
|
final month = DateFormat('MMM').format(createdAt);
|
|
final kota = data['kota'].toString();
|
|
final total = double.tryParse(data['total'].toString()) ?? 0;
|
|
|
|
pengirimanPerBulan.update(month, (v) => v + 1, ifAbsent: () => 1);
|
|
|
|
final key = '$month-$kota';
|
|
|
|
if (kotaSummary.containsKey(key)) {
|
|
kotaSummary[key]!['transaksi'] += 1;
|
|
kotaSummary[key]!['pendapatan'] += total;
|
|
} else {
|
|
kotaSummary[key] = {
|
|
'month': month,
|
|
'city': kota,
|
|
'transaksi': 1,
|
|
'pendapatan': total,
|
|
};
|
|
}
|
|
}
|
|
|
|
final monthlyList = pengirimanPerBulan.entries.map((e) {
|
|
return {
|
|
'month': e.key,
|
|
'pengiriman': e.value,
|
|
};
|
|
}).toList()
|
|
..sort((a, b) {
|
|
try {
|
|
final monthA = a['month']?.toString() ?? '';
|
|
final monthB = b['month']?.toString() ?? '';
|
|
|
|
return DateFormat('MMM')
|
|
.parse(monthA)
|
|
.month
|
|
.compareTo(
|
|
DateFormat('MMM').parse(monthB).month,
|
|
);
|
|
} catch (_) {
|
|
return 0;
|
|
}
|
|
});
|
|
|
|
|
|
final kotaList = kotaSummary.values
|
|
.where((k) => k['month'] == selectedMonth.value)
|
|
.toList()
|
|
..sort((a, b) =>
|
|
(b['pendapatan'] as double).compareTo(a['pendapatan'] as double));
|
|
|
|
monthlyData.assignAll(monthlyList);
|
|
|
|
// ✅ Pastikan selectedMonth valid
|
|
if (monthlyList.isNotEmpty) {
|
|
final months = monthlyList
|
|
.map((e) => e['month'] as String)
|
|
.toList();
|
|
|
|
if (!months.contains(selectedMonth.value)) {
|
|
selectedMonth.value = months.first;
|
|
}
|
|
}
|
|
topCities.assignAll(kotaList.take(10).toList());
|
|
}
|
|
|
|
void setSelectedMonth(String month) {
|
|
selectedMonth.value = month;
|
|
_updateData(); // 🔥 INI YANG PENTING
|
|
}
|
|
|
|
String formatRupiah(num value) {
|
|
final format = NumberFormat.currency(
|
|
locale: 'id_ID', symbol: 'Rp ', decimalDigits: 0);
|
|
return format.format(value);
|
|
}
|
|
}
|