first commit
This commit is contained in:
268
lib/Screens/DashBoard/numeric_axis.dart
Normal file
268
lib/Screens/DashBoard/numeric_axis.dart
Normal file
@@ -0,0 +1,268 @@
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile_pos/constant.dart';
|
||||
import 'package:mobile_pos/model/dashboard_overview_model.dart';
|
||||
|
||||
import 'chart_data.dart';
|
||||
|
||||
class DashboardChart extends StatefulWidget {
|
||||
const DashboardChart({Key? key, required this.model}) : super(key: key);
|
||||
|
||||
final DashboardOverviewModel model;
|
||||
|
||||
@override
|
||||
State<DashboardChart> createState() => _DashboardChartState();
|
||||
}
|
||||
|
||||
class _DashboardChartState extends State<DashboardChart> {
|
||||
List<ChartData> chartData = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
getData(widget.model);
|
||||
}
|
||||
|
||||
void getData(DashboardOverviewModel model) {
|
||||
chartData = [];
|
||||
for (int i = 0; i < model.data!.sales!.length; i++) {
|
||||
chartData.add(ChartData(
|
||||
model.data!.sales![i].date!,
|
||||
model.data!.sales![i].amount!.toDouble(),
|
||||
model.data!.purchases![i].amount!.toDouble(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Container(
|
||||
color: Colors.white,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: SizedBox(
|
||||
width: chartData.length * 50.0, // Adjust width based on the number of data points
|
||||
child: Stack(
|
||||
alignment: Alignment.topRight,
|
||||
children: [
|
||||
BarChart(
|
||||
BarChartData(
|
||||
alignment: BarChartAlignment.spaceAround,
|
||||
maxY: _getMaxY(),
|
||||
barTouchData: BarTouchData(enabled: false),
|
||||
titlesData: FlTitlesData(
|
||||
show: true,
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
getTitlesWidget: (value, meta) {
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: _getBottomTitles(value, meta),
|
||||
);
|
||||
},
|
||||
reservedSize: 42,
|
||||
),
|
||||
),
|
||||
rightTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: false,
|
||||
),
|
||||
),
|
||||
topTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false, reservedSize: 20),
|
||||
),
|
||||
leftTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
getTitlesWidget: _getLeftTitles,
|
||||
reservedSize: _getLeftTitleReservedSize(),
|
||||
),
|
||||
),
|
||||
),
|
||||
borderData: FlBorderData(
|
||||
show: false,
|
||||
),
|
||||
gridData: FlGridData(
|
||||
show: true,
|
||||
drawVerticalLine: false,
|
||||
drawHorizontalLine: true,
|
||||
getDrawingHorizontalLine: (value) {
|
||||
return const FlLine(
|
||||
color: Color(0xffD1D5DB),
|
||||
dashArray: [4, 4],
|
||||
strokeWidth: 1,
|
||||
);
|
||||
},
|
||||
),
|
||||
barGroups: _buildBarGroups(),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(),
|
||||
const Spacer(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 42),
|
||||
child: CustomPaint(
|
||||
size: Size(
|
||||
chartData.length * 50.0 - _getLeftTitleReservedSize(), // Adjust to match the width of the BarChart exactly
|
||||
0.1),
|
||||
painter: DashedBarPainter(
|
||||
barHeight: 1,
|
||||
barColor: const Color(0xffD1D5DB),
|
||||
dashWidth: 4,
|
||||
dashSpace: 4,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
double _getMaxY() {
|
||||
double maxY = 0;
|
||||
for (var data in chartData) {
|
||||
maxY = maxY > data.y ? maxY : data.y;
|
||||
maxY = maxY > data.y1 ? maxY : data.y1;
|
||||
}
|
||||
return maxY + 10;
|
||||
}
|
||||
|
||||
double _getLeftTitleReservedSize() {
|
||||
double maxY = _getMaxY();
|
||||
if (maxY < 999) {
|
||||
return 32;
|
||||
} else if (maxY < 1000) {
|
||||
return 35;
|
||||
} else if (maxY < 10000) {
|
||||
return 54;
|
||||
} else {
|
||||
return 50; // Add more cases if needed
|
||||
}
|
||||
}
|
||||
|
||||
List<BarChartGroupData> _buildBarGroups() {
|
||||
return chartData.asMap().entries.map((entry) {
|
||||
int index = entry.key;
|
||||
ChartData data = entry.value;
|
||||
|
||||
return BarChartGroupData(
|
||||
x: index,
|
||||
barRods: [
|
||||
BarChartRodData(
|
||||
toY: data.y,
|
||||
color: Colors.green,
|
||||
width: 6,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
),
|
||||
BarChartRodData(
|
||||
toY: data.y1,
|
||||
color: kMainColor,
|
||||
width: 6,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
),
|
||||
],
|
||||
barsSpace: 8,
|
||||
);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
Widget _getBottomTitles(double value, TitleMeta meta) {
|
||||
const style = TextStyle(
|
||||
color: Color(0xff4D4D4D),
|
||||
fontSize: 12,
|
||||
);
|
||||
|
||||
String text = chartData[value.toInt()].x;
|
||||
|
||||
return SideTitleWidget(
|
||||
space: 8,
|
||||
meta: TitleMeta(
|
||||
min: meta.min,
|
||||
max: meta.max,
|
||||
parentAxisSize: meta.parentAxisSize,
|
||||
axisPosition: meta.axisPosition,
|
||||
appliedInterval: meta.appliedInterval,
|
||||
sideTitles: meta.sideTitles,
|
||||
formattedValue: meta.formattedValue,
|
||||
axisSide: meta.axisSide,
|
||||
rotationQuarterTurns: meta.rotationQuarterTurns,
|
||||
),
|
||||
child: Text(text, style: style),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _getLeftTitles(double value, TitleMeta meta) {
|
||||
// Skip the highest value (already handled in your code)
|
||||
double maxY = _getMaxY();
|
||||
if (value == maxY) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
// Format the number
|
||||
String formattedValue;
|
||||
if (value >= 1e9) {
|
||||
formattedValue = '${(value / 1e9).toStringAsFixed(1)}B';
|
||||
} else if (value >= 1e6) {
|
||||
formattedValue = '${(value / 1e6).toStringAsFixed(1)}M';
|
||||
} else if (value >= 1e3) {
|
||||
formattedValue = '${(value / 1e3).toStringAsFixed(1)}K';
|
||||
} else {
|
||||
formattedValue = value.toInt().toString();
|
||||
}
|
||||
|
||||
return SideTitleWidget(
|
||||
meta: meta,
|
||||
child: Text(
|
||||
formattedValue,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
///---------------------------------dash line-------------------------------
|
||||
|
||||
class DashedBarPainter extends CustomPainter {
|
||||
final double barHeight;
|
||||
final Color barColor;
|
||||
final double dashWidth;
|
||||
final double dashSpace;
|
||||
|
||||
DashedBarPainter({
|
||||
required this.barHeight,
|
||||
required this.barColor,
|
||||
this.dashWidth = 4.0,
|
||||
this.dashSpace = 2.0,
|
||||
});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final paint = Paint()
|
||||
..color = barColor
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = barHeight;
|
||||
|
||||
final dashPath = Path();
|
||||
for (double i = 0; i < size.width; i += dashWidth + dashSpace) {
|
||||
dashPath.addRect(Rect.fromLTWH(i, 0, dashWidth, size.height));
|
||||
}
|
||||
canvas.drawPath(dashPath, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
}
|
||||
Reference in New Issue
Block a user