fix: fixing the grafik UI for sensor data

This commit is contained in:
Syaroful 2024-10-09 08:21:10 +07:00
parent fc4350f1dd
commit 04769c4f00
19 changed files with 530 additions and 325 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -2,7 +2,7 @@ class AppConstant {
static const String appName = 'Kebun Pintar'; static const String appName = 'Kebun Pintar';
static const String appVersion = '1.0.0'; static const String appVersion = '1.0.0';
static const String baseUrl = 'https://agrilinkvocpropisdev.id/api/v1'; static const String baseUrl = 'http://192.168.11.41:3333/api/';
static const String mqttServer = 'armadillo.rmq.cloudamqp.com'; static const String mqttServer = 'armadillo.rmq.cloudamqp.com';
static const String mqttUsername = 'obyskxhx:obyskxhx'; static const String mqttUsername = 'obyskxhx:obyskxhx';

View File

@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
Future<dynamic> showInfo(BuildContext context, String title, String content) {
return showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(title),
const SizedBox(height: 16),
Text(
style: Theme.of(context).textTheme.bodySmall,
content,
),
],
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('OK'),
)
],
),
);
}

View File

@ -0,0 +1,66 @@
class RelayResponse {
bool? success;
List<Relay>? data;
RelayResponse({this.success, this.data});
RelayResponse.fromJson(Map<String, dynamic> json) {
success = json['success'];
if (json['data'] != null) {
data = <Relay>[];
json['data'].forEach((v) {
data!.add(Relay.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['success'] = success;
if (this.data != null) {
data['data'] = this.data!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Relay {
int? id;
int? number;
String? enabledAt;
String? disabledAt;
bool? currentStatus;
String? createdAt;
String? updatedAt;
Relay(
{this.id,
this.number,
this.enabledAt,
this.disabledAt,
this.currentStatus,
this.createdAt,
this.updatedAt});
Relay.fromJson(Map<String, dynamic> json) {
id = json['id'];
number = json['number'];
enabledAt = json['enabled_at'];
disabledAt = json['disabled_at'];
currentStatus = json['current_status'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['number'] = number;
data['enabled_at'] = enabledAt;
data['disabled_at'] = disabledAt;
data['current_status'] = currentStatus;
data['created_at'] = createdAt;
data['updated_at'] = updatedAt;
return data;
}
}

View File

@ -1,4 +1,5 @@
import 'package:agrilink_vocpro/core/constant/app_contant.dart'; import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/data/model/relay_response.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
@ -9,8 +10,17 @@ class AppService {
), ),
); );
Future<void> getGreenHouseData() async { Future<RelayResponse> getRelayStatus() async {
try {} on DioException catch (e) { try {
await Future.delayed(const Duration(seconds: 3));
final result = await _dioWithoutInterceptor.get('get-relay');
if (result.statusCode == 200) {
final data = RelayResponse.fromJson(result.data);
return data;
} else {
throw Exception('Failed to load data');
}
} on DioException catch (e) {
if (kDebugMode) { if (kDebugMode) {
print(e); print(e);
} }

View File

@ -1,86 +1,125 @@
import 'dart:math';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/domain/service/mqtt_service.dart'; import 'package:agrilink_vocpro/domain/service/app_service.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class ControlProvider extends ChangeNotifier { class ControlProvider extends ChangeNotifier {
final MQTTService _mqttService = MQTTService(); final AppService _appService = AppService();
bool _control_1 = false; bool _control_1 = false;
bool get control_1 => _control_1; bool get control_1 => _control_1;
bool _control_2 = false;
bool get control_2 => _control_2;
ControlProvider() { ControlProvider() {
connectMqtt(); getRelayStatus();
} }
ResultState mqttState = ResultState.initial; // ResultState mqttState = ResultState.initial;
ResultState subscribeState = ResultState.initial; // ResultState subscribeState = ResultState.initial;
Future<void> connectMqtt() async { ResultState relayState = ResultState.initial;
mqttState = ResultState.loading;
subscribeState = ResultState.loading; // Future<void> connectMqtt() async {
// mqttState = ResultState.loading;
// subscribeState = ResultState.loading;
// notifyListeners();
// try {
// final result = await _mqttService.setupMqtt();
// if (result == ResultState.hasData) {
// mqttState = result;
// final result2 = await _mqttService.subscribeToRelayStatus();
// // if (result2 == true) {
// // subscribeState = ResultState.hasData;
// // _control_1 = true;
// // } else {
// // subscribeState = ResultState.hasData;
// // _control_1 = false;
// // }
// } else {
// mqttState = ResultState.error;
// }
// } catch (e) {
// mqttState = ResultState.error;
// print(e);
// }
// notifyListeners();
// }
Future<void> getRelayStatus() async {
relayState = ResultState.loading;
notifyListeners(); notifyListeners();
try { try {
final result = await _mqttService.setupMqtt(); final result = await _appService.getRelayStatus();
if (result == ResultState.hasData) { if (result.success == true) {
mqttState = result; for (var element in result.data!) {
final result2 = await _mqttService.subscribeToRelayStatus(); if (element.number == 1) {
// if (result2 == true) { switchControl1(element.currentStatus ?? false);
// subscribeState = ResultState.hasData; }
// _control_1 = true; if (element.number == 2) {
// } else { switchControl2(element.currentStatus ?? false);
// subscribeState = ResultState.hasData; }
// _control_1 = false; }
// } relayState = ResultState.hasData;
notifyListeners();
} else { } else {
mqttState = ResultState.error; relayState = ResultState.error;
notifyListeners();
} }
} catch (e) { } catch (e) {
mqttState = ResultState.error; relayState = ResultState.error;
print(e); notifyListeners();
}
notifyListeners();
}
Future<void> disconnectMqtt() async {
try {
await _mqttService.disconnectMqtt();
} catch (e) {
print(e);
rethrow;
}
notifyListeners();
}
@override
void dispose() {
disconnectMqtt();
super.dispose();
}
void switchControl1() {
_control_1 = !_control_1;
notifyListeners();
}
Future<ResultState> publishMessage(String topic, String message) async {
try {
final result = await _mqttService.publishMessage(topic, message);
return result;
} catch (e) {
print(e); print(e);
rethrow; rethrow;
} }
} }
Future<void> subscribeToTopic(String topic) async { // Future<void> disconnectMqtt() async {
try { // try {
await _mqttService.subscribeToTopic(topic); // await _mqttService.disconnectMqtt();
} catch (e) { // } catch (e) {
print(e); // print(e);
rethrow; // rethrow;
} // }
// notifyListeners();
// }
// @override
// void dispose() {
// disconnectMqtt();
// super.dispose();
// }
void switchControl1(bool value) {
_control_1 = value;
notifyListeners();
} }
void switchControl2(bool value) {
_control_2 = value;
notifyListeners();
}
// Future<ResultState> publishMessage(String topic, String message) async {
// try {
// final result = await _mqttService.publishMessage(topic, message);
// return result;
// } catch (e) {
// print(e);
// rethrow;
// }
// }
// Future<void> subscribeToTopic(String topic) async {
// try {
// await _mqttService.subscribeToTopic(topic);
// } catch (e) {
// print(e);
// rethrow;
// }
// }
} }

View File

@ -1,6 +1,8 @@
import 'package:agrilink_vocpro/core/constant/app_color.dart';
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart';
import 'package:agrilink_vocpro/features/control/provider/control_provider.dart'; import 'package:agrilink_vocpro/features/control/provider/control_provider.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
@ -11,6 +13,7 @@ class ControlScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final provider = Provider.of<ControlProvider>(context, listen: true);
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('Control', style: AppTheme.labelMedium), title: Text('Control', style: AppTheme.labelMedium),
@ -18,39 +21,114 @@ class ControlScreen extends StatelessWidget {
backgroundColor: Colors.white, backgroundColor: Colors.white,
scrolledUnderElevation: 0, scrolledUnderElevation: 0,
), ),
body: Consumer<ControlProvider>( body: RefreshIndicator(
builder: (context, provider, child) { onRefresh: () async =>
return SafeArea( await context.read<ControlProvider>().getRelayStatus(),
child: ListView( child: SafeArea(
children: [ child: ListView(
Center( children: [
child: provider.mqttState == ResultState.loading SizedBox(height: 16.h),
? const CupertinoActivityIndicator() GridView(
: provider.mqttState == ResultState.hasData padding: EdgeInsets.all(16.r),
? const Text('Terhubung ke Broker') physics: const NeverScrollableScrollPhysics(),
: const Text('Gagal terhubung ke Broker'), shrinkWrap: true,
), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
SizedBox(height: 16.h), crossAxisCount: 2,
ListTile( crossAxisSpacing: 16.r,
title: Text('Control 1', style: AppTheme.labelMedium), mainAxisSpacing: 16.r,
subtitle: const Text('Control 1 description'), childAspectRatio: 1.4.h,
trailing: Switch(
value: provider.control_1,
onChanged: (value) {
provider.control_1 == false
? provider.publishMessage(
'smartfarming/relay/232', 'ON')
: provider.publishMessage(
'smartfarming/relay/232', 'OFF');
provider.switchControl1();
},
), ),
), children: [
// Control lainnya... ControlButtonWidget(
], title: 'Katup Air',
), subtitle: 'Relay 1',
); isActive: provider.control_1,
}, onTap: () {},
),
ControlButtonWidget(
title: 'Lampu Utama',
subtitle: 'Relay 2',
isActive: provider.control_2,
onTap: () {},
),
]),
],
),
),
),
);
}
}
class ControlButtonWidget extends StatelessWidget {
const ControlButtonWidget({
super.key,
required this.title,
required this.subtitle,
required this.isActive,
required this.onTap,
});
final String title;
final String subtitle;
final bool isActive;
final Function() onTap;
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(16.r),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.r),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 1.r,
blurRadius: 16.r,
offset: Offset(0, 12.r),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: AppTheme.labelMedium),
Text(subtitle, style: AppTheme.labelSmall),
const Spacer(),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Consumer<ControlProvider>(
builder: (context, provider, child) {
switch (provider.relayState) {
case ResultState.loading:
return CircleAvatar(
radius: 20.r,
backgroundColor: Colors.transparent,
child: const CupertinoActivityIndicator(),
);
default:
return InkWell(
highlightColor: Colors.black,
onTap: onTap,
child: CircleAvatar(
radius: 20.r,
backgroundColor: isActive
? AppColor.secondary
: Colors.grey.shade400,
child: const Icon(
BootstrapIcons.power,
color: Colors.white,
),
),
);
}
},
),
],
)
],
), ),
); );
} }

View File

@ -23,7 +23,7 @@ class ConductivityScreen extends StatelessWidget {
padding: EdgeInsets.only(right: 16), padding: EdgeInsets.only(right: 16),
child: Icon( child: Icon(
Icons.electric_bolt_rounded, Icons.electric_bolt_rounded,
color: Colors.blue, color: Colors.teal,
), ),
) )
], ],
@ -38,7 +38,7 @@ class ConductivityScreen extends StatelessWidget {
Icon( Icon(
Icons.electric_bolt_rounded, Icons.electric_bolt_rounded,
size: 64.r, size: 64.r,
color: Colors.blue, color: Colors.teal,
), ),
Text('$value µS/cm', style: AppTheme.headline1), Text('$value µS/cm', style: AppTheme.headline1),
], ],
@ -70,7 +70,12 @@ class ConductivityScreen extends StatelessWidget {
borderRadius: BorderRadius.circular(16.w), borderRadius: BorderRadius.circular(16.w),
border: Border.all(color: Colors.grey.shade300, width: 1.w), border: Border.all(color: Colors.grey.shade300, width: 1.w),
), ),
child: const GarphicWidget(), child: const GarphicWidget(
gradientColors: [
Colors.cyan,
Colors.teal,
],
),
), ),
) )
], ],

View File

@ -110,13 +110,19 @@ class HumidityScreen extends StatelessWidget {
AspectRatio( AspectRatio(
aspectRatio: 2.h, aspectRatio: 2.h,
child: Container( child: Container(
margin: EdgeInsets.symmetric(horizontal: 16.w), margin: EdgeInsets.symmetric(horizontal: 16.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(16.w), borderRadius: BorderRadius.circular(16.w),
border: Border.all( border:
color: Colors.grey.shade300, width: 1.w)), Border.all(color: Colors.grey.shade300, width: 1.w)),
child: const GarphicWidget()), child: GarphicWidget(
gradientColors: [
Colors.blue.shade200,
Colors.blue,
],
),
),
), ),
SizedBox(height: 16.h), SizedBox(height: 16.h),
Padding( Padding(

View File

@ -104,13 +104,18 @@ class LightScreen extends StatelessWidget {
const Text('Grafik'), const Text('Grafik'),
SizedBox(height: 16.h), SizedBox(height: 16.h),
AspectRatio( AspectRatio(
aspectRatio: 1.5.h, aspectRatio: 1.8.h,
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade300, width: 1.w), border: Border.all(color: Colors.grey.shade300, width: 1.w),
borderRadius: BorderRadius.circular(16.w), borderRadius: BorderRadius.circular(16.w),
), ),
child: const GarphicWidget(), child: GarphicWidget(
gradientColors: [
Colors.yellow.shade100,
Colors.orange.shade200,
],
),
), ),
) )
// Row( // Row(

View File

@ -41,7 +41,7 @@ class NitrogenScreen extends StatelessWidget {
size: 64.r, size: 64.r,
color: Colors.blue, color: Colors.blue,
), ),
Text('$value µS/cm', style: AppTheme.headline1), Text('$value ppm', style: AppTheme.headline1),
], ],
), ),
SizedBox(height: 32.h), SizedBox(height: 32.h),
@ -71,7 +71,12 @@ class NitrogenScreen extends StatelessWidget {
borderRadius: BorderRadius.circular(16.w), borderRadius: BorderRadius.circular(16.w),
border: Border.all(color: Colors.grey.shade300, width: 1.w), border: Border.all(color: Colors.grey.shade300, width: 1.w),
), ),
child: const GarphicWidget(), child: GarphicWidget(
gradientColors: [
Colors.blue.shade200,
Colors.blue,
],
),
), ),
) )
], ],

View File

@ -167,7 +167,12 @@ class PhScreen extends StatelessWidget {
borderRadius: BorderRadius.circular(16.w), borderRadius: BorderRadius.circular(16.w),
border: Border.all(color: Colors.grey.shade300, width: 1.w), border: Border.all(color: Colors.grey.shade300, width: 1.w),
), ),
child: const GarphicWidget(), child: GarphicWidget(
gradientColors: [
Colors.amber.shade200,
Colors.orange,
],
),
), ),
) )
], ],

View File

@ -71,7 +71,12 @@ class PhosphorusScreen extends StatelessWidget {
borderRadius: BorderRadius.circular(16.w), borderRadius: BorderRadius.circular(16.w),
border: Border.all(color: Colors.grey.shade300, width: 1.w), border: Border.all(color: Colors.grey.shade300, width: 1.w),
), ),
child: const GarphicWidget(), child: GarphicWidget(
gradientColors: [
Colors.blue.shade200,
Colors.blue,
],
),
), ),
) )
], ],

View File

@ -71,7 +71,12 @@ class PotassiumScreen extends StatelessWidget {
borderRadius: BorderRadius.circular(16.w), borderRadius: BorderRadius.circular(16.w),
border: Border.all(color: Colors.grey.shade300, width: 1.w), border: Border.all(color: Colors.grey.shade300, width: 1.w),
), ),
child: const GarphicWidget(), child: const GarphicWidget(
gradientColors: [
Colors.teal,
Colors.green,
],
),
), ),
) )
], ],

View File

@ -1,4 +1,7 @@
import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/widgets/show_info.dart';
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -34,10 +37,8 @@ class SoilMoistureScreen extends StatelessWidget {
), ),
body: SafeArea( body: SafeArea(
child: ListView( child: ListView(
padding: EdgeInsets.all(16.w),
children: [ children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.05,
),
SizedBox( SizedBox(
height: 280.h, height: 280.h,
child: Stack( child: Stack(
@ -80,7 +81,47 @@ class SoilMoistureScreen extends StatelessWidget {
], ],
), ),
), ),
const SizedBox(height: 16), SizedBox(height: 16.h),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Soil Temperature',
style: AppTheme.labelMedium,
textAlign: TextAlign.center,
),
IconButton(
iconSize: 20.r,
color: Colors.blue,
onPressed: () {
showInfo(
context,
'Soil Temperature',
AppConstant.soilTempInfo,
);
},
icon: const Icon(BootstrapIcons.info_circle))
],
),
SizedBox(height: 16.h),
const Text('Grafik'),
SizedBox(height: 16.h),
AspectRatio(
aspectRatio: 1.8.h,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.w),
border: Border.all(color: Colors.grey.shade300, width: 1.w),
),
child: GarphicWidget(
gradientColors: [
Colors.blue.shade200,
Colors.blue,
],
),
),
)
], ],
), ),
), ),

View File

@ -1,5 +1,6 @@
import 'package:agrilink_vocpro/core/constant/app_constant.dart'; import 'package:agrilink_vocpro/core/constant/app_constant.dart';
import 'package:agrilink_vocpro/core/constant/app_theme.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:agrilink_vocpro/core/widgets/show_info.dart';
import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart';
import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -85,8 +86,7 @@ class SoilTemperatureScreen extends StatelessWidget {
], ],
), ),
), ),
const SizedBox(height: 16), SizedBox(height: 16.h),
const SizedBox(height: 16),
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
@ -218,7 +218,12 @@ class SoilTemperatureScreen extends StatelessWidget {
borderRadius: BorderRadius.circular(16.w), borderRadius: BorderRadius.circular(16.w),
border: Border.all(color: Colors.grey.shade300, width: 1.w), border: Border.all(color: Colors.grey.shade300, width: 1.w),
), ),
child: const GarphicWidget(), child: const GarphicWidget(
gradientColors: [
Colors.cyan,
Colors.amber,
],
),
), ),
) )
], ],
@ -226,31 +231,4 @@ class SoilTemperatureScreen extends StatelessWidget {
), ),
); );
} }
Future<dynamic> showInfo(BuildContext context, String title, String content) {
return showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(title),
const SizedBox(height: 16),
Text(
style: Theme.of(context).textTheme.bodySmall,
content,
),
],
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('OK'),
)
],
),
);
}
} }

View File

@ -75,7 +75,7 @@ class TemperatureScreen extends StatelessWidget {
), ),
progressBar: const GaugeBasicProgressBar( progressBar: const GaugeBasicProgressBar(
gradient: GaugeAxisGradient(colors: [ gradient: GaugeAxisGradient(colors: [
Colors.blue, Colors.white12,
Colors.orange, Colors.orange,
]), ]),
), ),
@ -211,7 +211,12 @@ class TemperatureScreen extends StatelessWidget {
borderRadius: BorderRadius.circular(16.w), borderRadius: BorderRadius.circular(16.w),
border: Border.all(color: Colors.grey.shade300, width: 1.w), border: Border.all(color: Colors.grey.shade300, width: 1.w),
), ),
child: const GarphicWidget(), child: const GarphicWidget(
gradientColors: [
Colors.cyan,
Colors.amber,
],
),
), ),
) )
], ],

View File

@ -1,191 +1,115 @@
import 'package:agrilink_vocpro/core/constant/app_color.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart';
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class GarphicWidget extends StatelessWidget { class GarphicWidget extends StatelessWidget {
const GarphicWidget({super.key, thi}); const GarphicWidget({super.key, required this.gradientColors});
final List<Color> gradientColors;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BarChart( return Padding(
BarChartData( padding: EdgeInsets.all(8.r),
barTouchData: barTouchData, child: LineChart(
titlesData: titlesData, mainData(),
borderData: borderData,
barGroups: barGroups,
gridData: const FlGridData(show: false),
alignment: BarChartAlignment.spaceAround,
maxY: 20,
), ),
); );
} }
}
BarTouchData get barTouchData => BarTouchData( Widget bottomTitleWidgets(double value, TitleMeta meta) {
enabled: false, TextStyle style = AppTheme.labelSmall;
touchTooltipData: BarTouchTooltipData( Widget text;
getTooltipColor: (group) => Colors.transparent, switch (value.toInt()) {
tooltipPadding: EdgeInsets.zero, case 1:
tooltipMargin: 8, text = Text('01.00', style: style);
getTooltipItem: ( break;
BarChartGroupData group, case 6:
int groupIndex, text = Text('06.00', style: style);
BarChartRodData rod, break;
int rodIndex, case 12:
) { text = Text('12.00', style: style);
return BarTooltipItem( break;
rod.toY.round().toString(), case 18:
const TextStyle( text = Text('18.00', style: style);
color: AppColor.textDark, break;
fontWeight: FontWeight.bold, case 23:
), text = Text('23.00', style: style);
); break;
}, default:
), text = Text('', style: style);
break;
}
return SideTitleWidget(
axisSide: meta.axisSide,
child: text,
); );
Widget getTitles(double value, TitleMeta meta) {
const style = TextStyle(
color: AppColor.textDark,
fontWeight: FontWeight.bold,
fontSize: 14,
);
String text;
switch (value.toInt()) {
case 0:
text = 'Mon';
break;
case 1:
text = 'Tue';
break;
case 2:
text = 'Wed';
break;
case 3:
text = 'Thu';
break;
case 4:
text = 'Fri';
break;
case 5:
text = 'Sat';
break;
case 6:
text = 'Sun';
break;
default:
text = '';
break;
} }
return SideTitleWidget(
axisSide: meta.axisSide,
space: 4,
child: Text(text, style: style),
);
}
FlTitlesData get titlesData => const FlTitlesData( LineChartData mainData() {
show: true, return LineChartData(
bottomTitles: AxisTitles( gridData: const FlGridData(
sideTitles: SideTitles( show: false,
showTitles: true, ),
reservedSize: 30, titlesData: FlTitlesData(
getTitlesWidget: getTitles, show: true,
rightTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 30,
interval: 1,
getTitlesWidget: bottomTitleWidgets,
),
),
leftTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
), ),
), ),
leftTitles: AxisTitles( borderData: FlBorderData(
sideTitles: SideTitles(showTitles: false), show: false,
border: Border.all(color: const Color(0xff37434d)),
), ),
topTitles: AxisTitles( minX: 0,
sideTitles: SideTitles(showTitles: false), maxX: 24,
), minY: 0,
rightTitles: AxisTitles( maxY: 100,
sideTitles: SideTitles(showTitles: false), lineBarsData: [
), LineChartBarData(
); spots: const [
FlSpot(0, 38),
FlBorderData get borderData => FlBorderData( FlSpot(1, 42),
show: false, FlSpot(2, 50),
); FlSpot(3, 53),
FlSpot(4, 58),
LinearGradient get _barsGradient => const LinearGradient( FlSpot(5, 64),
colors: [ FlSpot(7, 49),
AppColor.secondary, ],
AppColor.ternary, isCurved: true,
gradient: LinearGradient(
colors: gradientColors,
),
barWidth: 5,
isStrokeCapRound: true,
dotData: const FlDotData(
show: false,
),
belowBarData: BarAreaData(
show: true,
gradient: LinearGradient(
colors: gradientColors
.map((color) => color.withOpacity(0.3))
.toList()),
),
),
], ],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
); );
}
List<BarChartGroupData> get barGroups => [ }
BarChartGroupData(
x: 0,
barRods: [
BarChartRodData(
toY: 8,
gradient: _barsGradient,
)
],
showingTooltipIndicators: [0],
),
BarChartGroupData(
x: 1,
barRods: [
BarChartRodData(
toY: 10,
gradient: _barsGradient,
)
],
showingTooltipIndicators: [0],
),
BarChartGroupData(
x: 2,
barRods: [
BarChartRodData(
toY: 14,
gradient: _barsGradient,
)
],
showingTooltipIndicators: [0],
),
BarChartGroupData(
x: 3,
barRods: [
BarChartRodData(
toY: 15,
gradient: _barsGradient,
)
],
showingTooltipIndicators: [0],
),
BarChartGroupData(
x: 4,
barRods: [
BarChartRodData(
toY: 13,
gradient: _barsGradient,
)
],
showingTooltipIndicators: [0],
),
BarChartGroupData(
x: 5,
barRods: [
BarChartRodData(
toY: 10,
gradient: _barsGradient,
)
],
showingTooltipIndicators: [0],
),
BarChartGroupData(
x: 6,
barRods: [
BarChartRodData(
toY: 16,
gradient: _barsGradient,
)
],
showingTooltipIndicators: [0],
),
];

View File

@ -64,12 +64,12 @@ class ListDataFromCensorDht extends StatelessWidget {
DataDisplayerWidget( DataDisplayerWidget(
title: 'Temperature', title: 'Temperature',
subtitle: 'suhu greenhouse', subtitle: 'suhu greenhouse',
value: '28', value: '43',
unit: '°C', unit: '°C',
icon: BootstrapIcons.thermometer_half, icon: BootstrapIcons.thermometer_half,
color: Colors.white, color: Colors.white,
onTap: () async { onTap: () async {
await context.push('${AppRoute.temperature}/28'); await context.push('${AppRoute.temperature}/43');
}, },
), ),
DataDisplayerWidget( DataDisplayerWidget(