Skip to content

Reverse label order #1899

@Welnnys

Description

@Welnnys

Use case

image

I want to reverse the label order without reversing the circles ( my chart ) order. I tried a few things and nothing worked out so I am not entirely sure if this is possible or not.

Proposal

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:intl/intl.dart';

class OverviewPage extends StatefulWidget {
const OverviewPage({Key? key}) : super(key: key);

@OverRide
_OverviewPageState createState() => _OverviewPageState();
}

class _OverviewPageState extends State {
bool showTotalActivityTime = false;

@OverRide
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
'Overview',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
centerTitle: true,
automaticallyImplyLeading: false, // Removes the go back arrow
),
body: Center(
child: Column(
children: [
ElevatedButton(
onPressed: () {
setState(() {
showTotalActivityTime = !showTotalActivityTime;
});
},
child: Text(showTotalActivityTime ? 'Show Activity Counts' : 'Show Total Activity Time'),
),
Expanded(
child: FutureBuilder<List>(
future: showTotalActivityTime ? fetchTotalActivityTime() : fetchActivityCounts(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
return SizedBox(
height: 300, // Adjust height as needed
width: double.infinity, // Take full width
child: SfCircularChart(
legend: Legend(isVisible: true, position: LegendPosition.right), // Move legend to the right
series: [
RadialBarSeries<ChartData, String>(
dataSource: snapshot.data!,
xValueMapper: (ChartData data, _) => data.category,
yValueMapper: (ChartData data, _) => data.value,
dataLabelMapper: (ChartData data, _) => data.formattedTime,
dataLabelSettings: const DataLabelSettings(isVisible: true),
// Adjust the thickness of the circle lines
trackBorderWidth: 2, // Adjust this value to make the circle lines thinner or thicker
// Adjust the space between each circle
gap: '17%', // Adjust this value to add space between the circles
// Adjust the thickness of the circles
innerRadius: '10%', // Adjust this value to make the circles thinner or thicker
)
],
),
);
}
},
),
),
],
),
),
);
}

Future<List> fetchActivityCounts() async {
final userUID = FirebaseAuth.instance.currentUser?.uid;
if (userUID != null) {
final now = DateTime.now();
final currentMonthYear = DateFormat('MM-yyyy').format(now);

final querySnapshot = await FirebaseFirestore.instance
    .collection('users')
    .doc(userUID)
    .collection(currentMonthYear)
    .where('ActivityName', isNotEqualTo: null)
    .where('ActivityName', isNotEqualTo: 'placeholder')
    .get();

if (querySnapshot.docs.isEmpty) {
  // Return example chart data if no records are found
  return generateExampleChartData();
}

// Aggregate count of records for each activity
Map<String, int> activityCounts = {};
for (var doc in querySnapshot.docs) {
  final activityName = doc['ActivityName'] as String;
  activityCounts[activityName] = (activityCounts[activityName] ?? 0) + 1;
}

// Convert to ChartData objects
List<ChartData> chartData = [];
activityCounts.forEach((activity, count) {
  final formattedTime = '$count $activity records';
  chartData.add(ChartData(activity, count.toDouble(), formattedTime));
});

// Sort the chartData list by value in descending order
chartData.sort((a, b) => b.value.compareTo(a.value));

// Get only the first 5 elements
chartData = chartData.take(5).toList();

// Reverse the list so that the biggest count is first
chartData = chartData.reversed.toList();

return chartData;

}
return [];
}

Future<List> fetchTotalActivityTime() async {
final userUID = FirebaseAuth.instance.currentUser?.uid;
if (userUID != null) {
final now = DateTime.now();
final currentMonthYear = DateFormat('MM-yyyy').format(now);

final querySnapshot = await FirebaseFirestore.instance
    .collection('users')
    .doc(userUID)
    .collection(currentMonthYear)
    .where('ActivityName', isNotEqualTo: null)
    .where('ActivityName', isNotEqualTo: 'placeholder')
    .get();

if (querySnapshot.docs.isEmpty) {
  // Return example chart data if no records are found
  return generateExampleChartData();
}

// Aggregate total activity time for each activity
Map<String, double> activityTimes = {};
for (var doc in querySnapshot.docs) {
  final activityName = doc['ActivityName'] as String;
  final activityTimeRaw = doc['ActivityTime'] as String;

  double activityTime = parseActivityTime(activityTimeRaw);

  // Convert time from minutes to hours
  double activityTimeInHours = activityTime / 60.0;

  activityTimes[activityName] = (activityTimes[activityName] ?? 0) + activityTimeInHours;
}

// Convert to ChartData objects
List<ChartData> chartData = [];
activityTimes.forEach((activity, time) {
  final hours = time.floor();
  final minutes = ((time - hours) * 60).toInt();
  final formattedTime = '$hours hours $minutes minutes';
  chartData.add(ChartData(activity, time, formattedTime));
});

// Sort the chartData list by value in descending order
chartData.sort((a, b) => b.value.compareTo(a.value));

// Get only the first 5 elements
chartData = chartData.take(5).toList();

// Reverse the list so that the biggest time is first
chartData = chartData.reversed.toList();

return chartData;

}
return [];
}

List generateExampleChartData() {
// Example data
List exampleData = [
ChartData('Example 1', 3, '3 records'),
ChartData('Example 2', 5, '5 records'),
ChartData('Example 3', 10, '10 records'),
ChartData('Example 4', 15, '15 records'),
ChartData('Example 5', 20, '20 records'),
];

return exampleData;
}

double parseActivityTime(String activityTime) {
// Initialize total time in minutes
double totalMinutes = 0.0;

// Use regular expressions to extract the values
final hoursRegex = RegExp(r'(\d+)\s*hours?');
final minutesRegex = RegExp(r'(\d+)\s*mins?');

final hoursMatch = hoursRegex.firstMatch(activityTime);
final minutesMatch = minutesRegex.firstMatch(activityTime);

if (hoursMatch != null) {
  totalMinutes += double.parse(hoursMatch.group(1)!) * 60;
}
if (minutesMatch != null) {
  totalMinutes += double.parse(minutesMatch.group(1)!);
}

return totalMinutes;

}
}

class ChartData {
ChartData(this.category, this.value, this.formattedTime);
final String category;
final double value;
final String formattedTime;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    chartsCharts componentsolvedSolved the query using existing solutionsworkaround availableWorkaround available to overcome the query

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions