E41220983_MuhamadSugengCahy.../praresi/lib/presentation/views/analisis_view.dart

297 lines
14 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:fl_chart/fl_chart.dart';
import '../controllers/analisis_controller.dart';
class AnalisisView extends StatelessWidget {
const AnalisisView({super.key});
@override
Widget build(BuildContext context) {
final AnalisisController controller = Get.put(AnalisisController());
return Scaffold(
extendBodyBehindAppBar: true,
body: Obx(() {
final monthlyData = controller.monthlyData;
final topCities = controller.topCities;
final selectedMonth = controller.selectedMonth.value;
return Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF1976D2), Color(0xFFE3F2FD)],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: SafeArea(
child: Column(
children: [
const SizedBox(height: 12),
// 🔹 Grafik Pengiriman Bulanan
Container(
margin:
const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(18),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Column(
children: [
Row(
children: const [
Icon(Icons.bar_chart, color: Color(0xFF1976D2)),
SizedBox(width: 8),
Text(
"Pengiriman Bulanan",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black87,
fontSize: 16,
),
),
],
),
const SizedBox(height: 12),
monthlyData.isEmpty
? const SizedBox(
height: 200,
child: Center(
child: Text(
"Belum ada data pengiriman",
style: TextStyle(color: Colors.black54),
),
),
)
: SizedBox(
height: 220,
child: BarChart(
BarChartData(
alignment: BarChartAlignment.spaceAround,
gridData: FlGridData(show: false),
borderData: FlBorderData(show: false),
titlesData: FlTitlesData(
leftTitles: const AxisTitles(
sideTitles:
SideTitles(showTitles: false),
),
topTitles: const AxisTitles(
sideTitles:
SideTitles(showTitles: false),
),
rightTitles: const AxisTitles(
sideTitles:
SideTitles(showTitles: false),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: (value, _) {
final index = value.toInt();
if (index >= 0 &&
index < monthlyData.length) {
return Padding(
padding:
const EdgeInsets.only(top: 6),
child: Text(
monthlyData[index]['month'],
style: const TextStyle(
fontSize: 12,
color: Colors.black87,
fontWeight: FontWeight.w500,
),
),
);
}
return const SizedBox.shrink();
},
),
),
),
barGroups:
monthlyData.asMap().entries.map((e) {
final pengiriman =
(e.value['pengiriman'] as num)
.toDouble();
return BarChartGroupData(
x: e.key,
barRods: [
BarChartRodData(
toY: pengiriman,
gradient: const LinearGradient(
colors: [
Color(0xFF1976D2),
Color(0xFF64B5F6),
],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
),
width: 18,
borderRadius:
BorderRadius.circular(6),
),
],
);
}).toList(),
),
),
),
// 🔹 Tampilkan jumlah di atas batang
if (monthlyData.isNotEmpty) const SizedBox(height: 12),
if (monthlyData.isNotEmpty)
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: monthlyData.map((e) {
return Text(
e['pengiriman'].toString(),
style: const TextStyle(
fontSize: 12,
color: Colors.black54,
fontWeight: FontWeight.w600,
),
);
}).toList(),
),
],
),
),
// 🔹 Top Kota Tujuan per Bulan
Expanded(
child: Container(
width: double.infinity,
margin: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(18),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.08),
blurRadius: 8,
offset: const Offset(0, 3),
),
],
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: const [
Icon(Icons.location_city,
color: Color(0xFF1976D2)),
SizedBox(width: 6),
Text(
"Top 10 Kota Tujuan",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black87,
fontSize: 16,
),
),
],
),
// 🔹 Dropdown pilih bulan
DropdownButton<String>(
value: selectedMonth,
items: controller.monthlyData
.map((e) => DropdownMenuItem<String>(
value: e['month'],
child: Text(e['month']),
))
.toList(),
onChanged: (value) {
if (value != null) {
controller.setSelectedMonth(value);
}
},
underline: const SizedBox(),
style: const TextStyle(
color: Colors.black87, fontSize: 14),
icon: const Icon(Icons.arrow_drop_down,
color: Color(0xFF1976D2)),
),
],
),
),
const Divider(height: 1, color: Color(0xFFE0E0E0)),
Expanded(
child: topCities.isEmpty
? const Center(
child: Text(
"Tidak ada data untuk bulan ini",
style: TextStyle(color: Colors.black54),
),
)
: ListView.separated(
padding: const EdgeInsets.symmetric(
horizontal: 12),
itemCount: topCities.length,
separatorBuilder: (_, __) => Divider(
color: Colors.grey.shade200,
height: 1,
),
itemBuilder: (context, index) {
final city = topCities[index];
return ListTile(
contentPadding:
const EdgeInsets.symmetric(
horizontal: 8, vertical: 6),
leading: CircleAvatar(
backgroundColor: Colors.blue.shade50,
child: Text(
'${index + 1}',
style: const TextStyle(
color: Color(0xFF1976D2),
fontWeight: FontWeight.bold,
),
),
),
title: Text(
city['city'],
style: const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 14,
),
),
subtitle: Text(
"Pengiriman: ${city['transaksi']} kali\nPendapatan: ${controller.formatRupiah(city['pendapatan'])}",
style: const TextStyle(fontSize: 12),
),
// trailing: const Icon(
// Icons.chevron_right_rounded,
// color: Colors.grey,
// ),
);
},
),
),
],
),
),
),
const SizedBox(height: 16),
],
),
),
);
}),
);
}
}