109 lines
3.4 KiB
Dart
109 lines
3.4 KiB
Dart
import 'package:fl_chart/fl_chart.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:intl/intl.dart';
|
|
|
|
class DataPoint {
|
|
DataPoint({required this.date, required this.progress});
|
|
DateTime date;
|
|
double progress;
|
|
}
|
|
|
|
class GraphWidget extends ConsumerStatefulWidget {
|
|
GraphWidget({super.key});
|
|
|
|
@override
|
|
ConsumerState<ConsumerStatefulWidget> createState() => _GraphWidgetState();
|
|
|
|
final entries = <DataPoint>[
|
|
DataPoint(date: DateTime(2024, 7, 4), progress: 1),
|
|
DataPoint(date: DateTime(2024, 7, 5), progress: 0.5),
|
|
DataPoint(date: DateTime(2024, 7, 6), progress: 1.25),
|
|
DataPoint(date: DateTime(2024, 7, 7), progress: 0.75),
|
|
];
|
|
}
|
|
|
|
class _GraphWidgetState extends ConsumerState<GraphWidget> {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final firstDate = widget.entries[0].date;
|
|
final flSpots = <FlSpot>[];
|
|
for (final dataPoint in widget.entries) {
|
|
final xValue = _daysBetween(firstDate, dataPoint.date).toDouble();
|
|
final lcbd = FlSpot(xValue, dataPoint.progress);
|
|
flSpots.add(lcbd);
|
|
}
|
|
final df = DateFormat('dd. MMMM');
|
|
|
|
return Column(
|
|
children: [
|
|
SizedBox(
|
|
width: MediaQuery.of(context).size.width * 0.85,
|
|
height: MediaQuery.of(context).size.height * 0.5,
|
|
child: LineChart(
|
|
LineChartData(
|
|
minY: 0,
|
|
maxY: 1.5,
|
|
lineBarsData: [
|
|
LineChartBarData(spots: flSpots, isCurved: true),
|
|
],
|
|
gridData: const FlGridData(show: false),
|
|
extraLinesData: ExtraLinesData(
|
|
horizontalLines: [
|
|
HorizontalLine(
|
|
y: 1,
|
|
color: Colors.red,
|
|
),
|
|
],
|
|
),
|
|
titlesData: FlTitlesData(
|
|
rightTitles: const AxisTitles(
|
|
sideTitles: SideTitles(
|
|
reservedSize: 30,
|
|
interval: 20,
|
|
),
|
|
),
|
|
topTitles: const AxisTitles(
|
|
sideTitles: SideTitles(
|
|
interval: 20,
|
|
),
|
|
),
|
|
leftTitles: AxisTitles(
|
|
sideTitles: SideTitles(
|
|
showTitles: true,
|
|
reservedSize: 30,
|
|
getTitlesWidget: (value, meta) => Text(value.toString()),
|
|
interval: 0.25,
|
|
),
|
|
),
|
|
bottomTitles: AxisTitles(
|
|
sideTitles: SideTitles(
|
|
getTitlesWidget: (value, meta) => Text(
|
|
df.format(
|
|
DateTime(
|
|
firstDate.year,
|
|
firstDate.month,
|
|
firstDate.day,
|
|
).add(Duration(days: value.round())),
|
|
),
|
|
),
|
|
showTitles: true,
|
|
interval: 1,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
const Text('You worked for X hours this past week'),
|
|
const Text('Out of a total of Y hours planned'),
|
|
],
|
|
);
|
|
}
|
|
|
|
int _daysBetween(DateTime from, DateTime to) {
|
|
final d1 = DateTime(from.year, from.month, from.day);
|
|
final d2 = DateTime(to.year, to.month, to.day);
|
|
return (d2.difference(d1).inHours / 24).round();
|
|
}
|
|
}
|