Frontend first draft
This commit is contained in:
91
frontend/pweb/lib/pages/report/charts/status.dart
Normal file
91
frontend/pweb/lib/pages/report/charts/status.dart
Normal file
@@ -0,0 +1,91 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||
|
||||
import 'package:pshared/models/payment/status.dart';
|
||||
import 'package:pshared/models/payment/operation.dart';
|
||||
|
||||
|
||||
class StatusChart extends StatelessWidget {
|
||||
final List<OperationItem> operations;
|
||||
|
||||
const StatusChart({super.key, required this.operations});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// 1) Compute counts
|
||||
final counts = <OperationStatus, int>{};
|
||||
for (var op in operations) {
|
||||
counts[op.status] = (counts[op.status] ?? 0) + 1;
|
||||
}
|
||||
final items = counts.entries
|
||||
.map((e) => _ChartData(e.key, e.value.toDouble()))
|
||||
.toList();
|
||||
final maxCount = items.map((e) => e.count.toInt()).fold<int>(0, max);
|
||||
|
||||
final theme = Theme.of(context);
|
||||
final barColor = theme.colorScheme.secondary;
|
||||
final caption = theme.textTheme.labelMedium;
|
||||
|
||||
return SizedBox(
|
||||
height: 200,
|
||||
child: Card(
|
||||
margin: const EdgeInsets.all(16),
|
||||
elevation: 2,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 8),
|
||||
child: SfCartesianChart(
|
||||
// ─── Axes ─────────────────────────────────────────
|
||||
primaryXAxis: CategoryAxis(
|
||||
labelStyle: caption,
|
||||
majorGridLines: const MajorGridLines(width: 0),
|
||||
),
|
||||
primaryYAxis: NumericAxis(
|
||||
minimum: 0,
|
||||
maximum: (maxCount + 1).toDouble(),
|
||||
interval: 1,
|
||||
labelStyle: caption,
|
||||
majorGridLines: MajorGridLines(
|
||||
color: theme.dividerColor.withAlpha(76),
|
||||
width: 1,
|
||||
dashArray: <double>[4, 2],
|
||||
),
|
||||
),
|
||||
|
||||
// ─── Enable tooltips ───────────────────────────────
|
||||
legend: Legend(isVisible: false),
|
||||
tooltipBehavior: TooltipBehavior(
|
||||
enable: true,
|
||||
header: '', // omit series name in header
|
||||
format: 'point.x : point.y', // e.g. "Init : 2"
|
||||
),
|
||||
|
||||
// ─── Bar series with tooltip enabled ───────────────
|
||||
series: <ColumnSeries<_ChartData, String>>[
|
||||
ColumnSeries<_ChartData, String>(
|
||||
dataSource: items,
|
||||
xValueMapper: (d, _) => d.status.localized(context),
|
||||
yValueMapper: (d, _) => d.count,
|
||||
color: barColor,
|
||||
width: 0.6,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(4)),
|
||||
enableTooltip: true, // <— turn on for this series
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ChartData {
|
||||
final OperationStatus status;
|
||||
final double count;
|
||||
_ChartData(this.status, this.count);
|
||||
}
|
||||
Reference in New Issue
Block a user