160 lines
5.0 KiB
Dart
160 lines
5.0 KiB
Dart
import 'dart:math';
|
|
|
|
import 'package:fl_chart/fl_chart.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:hoshan/data/model/report_model.dart';
|
|
import 'package:hoshan/ui/theme/responsive.dart';
|
|
import 'package:hoshan/ui/theme/text.dart';
|
|
import 'package:hoshan/ui/widgets/components/chart/indocator.dart';
|
|
|
|
class CustomePiChart extends StatefulWidget {
|
|
final List<Report> points;
|
|
|
|
const CustomePiChart({super.key, required this.points});
|
|
|
|
@override
|
|
State<CustomePiChart> createState() => _CustomePiChartState();
|
|
}
|
|
|
|
class _CustomePiChartState extends State<CustomePiChart> {
|
|
int touchedIndex = -1;
|
|
|
|
bool valid = false;
|
|
|
|
late int allPointCoinsUsage =
|
|
widget.points.fold(0, (sum, point) => sum + (point.coinUsage ?? 0));
|
|
Color getRandomColor(Set<Color> existingColors) {
|
|
Random random = Random();
|
|
Color newColor;
|
|
|
|
do {
|
|
newColor = Color.fromARGB(
|
|
255, // Full opacity
|
|
random.nextInt(256), // Red (0-255)
|
|
random.nextInt(256), // Green (0-255)
|
|
random.nextInt(256), // Blue (0-255)
|
|
);
|
|
} while (
|
|
existingColors.contains(newColor)); // Keep generating if color exists
|
|
|
|
existingColors.add(newColor); // Add new unique color to the set
|
|
return newColor;
|
|
}
|
|
|
|
late Set<Color> usedColors = {}; // Track used colors
|
|
|
|
late List<Color> colors = List.generate(
|
|
widget.points.length,
|
|
(index) => getRandomColor(usedColors),
|
|
);
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
for (var report in widget.points) {
|
|
if (report.coinUsage != null && report.coinUsage! > 0) {
|
|
valid = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
valid
|
|
? AspectRatio(
|
|
aspectRatio: Responsive(context).isDesktop() ? 2 : 1 / 1,
|
|
child: Stack(
|
|
children: [
|
|
PieChart(
|
|
PieChartData(
|
|
pieTouchData: PieTouchData(
|
|
touchCallback:
|
|
(FlTouchEvent event, pieTouchResponse) {
|
|
setState(() {
|
|
if (!event.isInterestedForInteractions ||
|
|
pieTouchResponse == null ||
|
|
pieTouchResponse.touchedSection == null) {
|
|
touchedIndex = -1;
|
|
return;
|
|
}
|
|
touchedIndex = pieTouchResponse
|
|
.touchedSection!.touchedSectionIndex;
|
|
});
|
|
},
|
|
),
|
|
borderData: FlBorderData(
|
|
show: false,
|
|
),
|
|
sectionsSpace: 4,
|
|
centerSpaceRadius: 64,
|
|
sections: showingSections(),
|
|
),
|
|
),
|
|
Positioned.fill(
|
|
child: Center(
|
|
child: Text(
|
|
'سکه',
|
|
style: AppTextStyles.headline3.copyWith(
|
|
color: Theme.of(context).colorScheme.onSurface),
|
|
),
|
|
))
|
|
],
|
|
),
|
|
)
|
|
: const SizedBox(
|
|
height: 24,
|
|
),
|
|
Directionality(
|
|
textDirection: TextDirection.rtl,
|
|
child: ListView.builder(
|
|
itemCount: widget.points.length,
|
|
shrinkWrap: true,
|
|
physics: const BouncingScrollPhysics(),
|
|
itemBuilder: (context, index) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 4.0),
|
|
child: Indicator(
|
|
count: '${widget.points[index].messagesCount} پیام',
|
|
color: colors[index],
|
|
text: widget.points[index].date ?? '',
|
|
isSquare: false,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
List<PieChartSectionData> showingSections() {
|
|
return List.generate(widget.points.length, (index) {
|
|
final isTouched = index == touchedIndex;
|
|
final fontSize = isTouched ? 16.0 : 12.0;
|
|
final radius = isTouched ? 60.0 : 50.0;
|
|
const shadows = [Shadow(color: Colors.black, blurRadius: 2)];
|
|
final point = widget.points[index];
|
|
return PieChartSectionData(
|
|
color: colors[index],
|
|
value: max((point.coinUsage! * 100) / allPointCoinsUsage, 3.5),
|
|
radius: radius,
|
|
title: '',
|
|
badgeWidget: Text(
|
|
'${point.coinUsage}',
|
|
textDirection: TextDirection.rtl,
|
|
textAlign: TextAlign.center,
|
|
style: AppTextStyles.body3.copyWith(
|
|
fontSize: fontSize,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.white,
|
|
shadows: shadows,
|
|
),
|
|
),
|
|
);
|
|
});
|
|
}
|
|
}
|