diff --git a/agrilink_vocpro/lib/core/constant/app_constant.dart b/agrilink_vocpro/lib/core/constant/app_constant.dart index e464b3a..0aa7d73 100644 --- a/agrilink_vocpro/lib/core/constant/app_constant.dart +++ b/agrilink_vocpro/lib/core/constant/app_constant.dart @@ -2,7 +2,7 @@ class AppConstant { static const String appName = 'Kebun Pintar'; static const String appVersion = '1.0.0'; - static const String baseUrl = 'http://192.168.11.41:3333/api/'; + static const String baseUrl = 'https://jx027dj4-3333.asse.devtunnels.ms/api'; static const String mqttServer = 'armadillo.rmq.cloudamqp.com'; static const String mqttUsername = 'obyskxhx:obyskxhx'; @@ -10,4 +10,19 @@ class AppConstant { static const String soilTempInfo = 'Suhu tanah mengacu pada suhu tanah di permukaan atau pada kedalaman tertentu, yang berperan penting dalam pertumbuhan tanaman dan proses pertanian. Suhu ini memengaruhi perkecambahan benih, aktivitas akar, serta penyerapan air dan nutrisi, yang semuanya esensial bagi perkembangan tanaman. Selain itu, suhu tanah juga memengaruhi aktivitas mikroorganisme yang berkontribusi pada kesuburan tanah. Dalam pertanian pintar, sensor suhu tanah sering digunakan untuk memantau dan mengoptimalkan kondisi tanah, memastikan tanaman tumbuh dalam rentang suhu yang ideal.'; + + static const String npk1 = 'npk1'; + static const String npk2 = 'npk2'; + static const String dht = 'dht'; + + static const String soilTemp = 'soilTemperature'; + static const String soilMoisture = 'soilMoisture'; + static const String airTemp = 'viciTemperature'; + static const String humidity = 'humidity'; + static const String lightIntensity = 'lightIntensity'; + static const String conductivity = 'conductivity'; + static const String ph = 'ph'; + static const String nitrogen = 'nitrogen'; + static const String phosphorus = 'phosphorus'; + static const String potassium = 'potassium'; } diff --git a/agrilink_vocpro/lib/core/extension/extention.dart b/agrilink_vocpro/lib/core/extension/extention.dart index 095604d..a19384f 100644 --- a/agrilink_vocpro/lib/core/extension/extention.dart +++ b/agrilink_vocpro/lib/core/extension/extention.dart @@ -10,6 +10,12 @@ String dateFormater(String date) { return formatter.format(dateTime); } +String dateFormatterShort(String date) { + final DateTime dateTime = DateTime.parse(date); + final DateFormat formatter = DateFormat('yyyy-MM-dd'); + return formatter.format(dateTime); +} + String getGreeting(String time) { DateTime parsedTime = DateTime.parse(time); int hour = parsedTime.hour; diff --git a/agrilink_vocpro/lib/domain/service/app_service.dart b/agrilink_vocpro/lib/domain/service/app_service.dart index 0d9cb8a..a33557e 100644 --- a/agrilink_vocpro/lib/domain/service/app_service.dart +++ b/agrilink_vocpro/lib/domain/service/app_service.dart @@ -1,5 +1,8 @@ import 'package:agrilink_vocpro/core/constant/app_constant.dart'; +import 'package:agrilink_vocpro/core/extension/extention.dart'; import 'package:agrilink_vocpro/data/model/relay_response.dart'; +import 'package:agrilink_vocpro/features/home/model/latest_data_response.dart'; +import 'package:agrilink_vocpro/features/home/model/npk1_soil_temp_grafik.dart'; import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; @@ -27,4 +30,47 @@ class AppService { rethrow; } } + + Future getNpk1SoilTempGrafik({ + required String metric, + required String sensor, + }) async { + String dateNow = DateTime.now().toString(); + String dateYesterday = + DateTime.now().subtract(Duration(days: 1)).toString(); + final formatedDateNow = dateFormatterShort(dateNow); + final formatedDateYesterday = dateFormatterShort(dateYesterday); + try { + final result = await _dioWithoutInterceptor.get( + '/sensor/getData?metric=$metric&range[start]=$formatedDateYesterday&range[end]=$formatedDateNow&range[time_range]=HOURLY&sensor=$sensor', + ); + if (result.statusCode == 200) { + print(result.data.toString()); + final data = Npk1SoilTempGrafik.fromJson(result.data); + return data; + } else { + throw Exception('Failed to load data'); + } + } on DioException catch (e) { + print(e); + rethrow; + } + } + + Future getLatestData() async { + try { + final result = await _dioWithoutInterceptor.get( + '/sensor/getLatest', + ); + if (result.statusCode == 200) { + final data = LatestDataResponse.fromJson(result.data); + return data; + } else { + throw Exception('Failed to load data'); + } + } on DioException catch (e) { + print(e); + rethrow; + } + } } diff --git a/agrilink_vocpro/lib/features/control/provider/control_provider.dart b/agrilink_vocpro/lib/features/control/provider/control_provider.dart index 1582766..6e0dbad 100644 --- a/agrilink_vocpro/lib/features/control/provider/control_provider.dart +++ b/agrilink_vocpro/lib/features/control/provider/control_provider.dart @@ -52,6 +52,7 @@ class ControlProvider extends ChangeNotifier { relayState = ResultState.loading; notifyListeners(); try { + print('try to get relay status...'); final result = await _appService.getRelayStatus(); if (result.success == true) { for (var element in result.data!) { diff --git a/agrilink_vocpro/lib/features/control/view/control_screen.dart b/agrilink_vocpro/lib/features/control/view/control_screen.dart index f1aa872..10b6d21 100644 --- a/agrilink_vocpro/lib/features/control/view/control_screen.dart +++ b/agrilink_vocpro/lib/features/control/view/control_screen.dart @@ -61,33 +61,38 @@ class ControlScreen extends StatelessWidget { }), SizedBox(height: 16.h), GridView( - padding: EdgeInsets.all(16.r), - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 16.r, - mainAxisSpacing: 16.r, - childAspectRatio: 1.4.h, + padding: EdgeInsets.all(16.r), + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 16.r, + mainAxisSpacing: 16.r, + childAspectRatio: 1.35.h, + ), + children: [ + ControlButtonWidget( + title: 'Katup Air', + subtitle: 'Relay 1', + isActive: provider.control_1, + onTap: () { + provider.control_1 != true + ? provider.switchControl1(true) + : provider.switchControl1(false); + }, ), - children: [ - ControlButtonWidget( - title: 'Katup Air', - subtitle: 'Relay 1', - isActive: provider.control_1, - onTap: () { - provider.control_1 != true - ? provider.switchControl1(true) - : provider.switchControl1(false); - }, - ), - ControlButtonWidget( - title: 'Lampu Utama', - subtitle: 'Relay 2', - isActive: provider.control_2, - onTap: () {}, - ), - ]), + ControlButtonWidget( + title: 'Lampu Utama', + subtitle: 'Relay 2', + isActive: provider.control_2, + onTap: () { + provider.control_2 != true + ? provider.switchControl2(true) + : provider.switchControl2(false); + }, + ), + ], + ), ], ), ), diff --git a/agrilink_vocpro/lib/features/home/model/dht_graphic_response.dart b/agrilink_vocpro/lib/features/home/model/dht_graphic_response.dart new file mode 100644 index 0000000..39cda05 --- /dev/null +++ b/agrilink_vocpro/lib/features/home/model/dht_graphic_response.dart @@ -0,0 +1,75 @@ +class DhtGraphicResponse { + DataDht? data; + int? statusCode; + String? message; + + DhtGraphicResponse({this.data, this.statusCode, this.message}); + + DhtGraphicResponse.fromJson(Map json) { + data = json['data'] != null ? DataDht.fromJson(json['data']) : null; + statusCode = json['statusCode']; + message = json['message']; + } + + Map toJson() { + final Map data = {}; + if (this.data != null) { + data['data'] = this.data!.toJson(); + } + data['statusCode'] = statusCode; + data['message'] = message; + return data; + } +} + +class DataDht { + List? dht; + + DataDht({this.dht}); + + DataDht.fromJson(Map json) { + if (json['dht'] != null) { + dht = []; + json['dht'].forEach((v) { + dht!.add(Dht.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = {}; + if (dht != null) { + data['dht'] = dht!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Dht { + int? hour; + double? vicitemperatureAvg; + double? vicihumidityAvg; + double? viciluminosityAvg; + + Dht( + {this.hour, + this.vicitemperatureAvg, + this.vicihumidityAvg, + this.viciluminosityAvg}); + + Dht.fromJson(Map json) { + hour = json['hour']; + vicitemperatureAvg = json['vicitemperature_avg']; + vicihumidityAvg = json['vicihumidity_avg']; + viciluminosityAvg = json['viciluminosity_avg']; + } + + Map toJson() { + final Map data = {}; + data['hour'] = hour; + data['vicitemperature_avg'] = vicitemperatureAvg; + data['vicihumidity_avg'] = vicihumidityAvg; + data['viciluminosity_avg'] = viciluminosityAvg; + return data; + } +} diff --git a/agrilink_vocpro/lib/features/home/model/latest_data_response.dart b/agrilink_vocpro/lib/features/home/model/latest_data_response.dart new file mode 100644 index 0000000..270e8b6 --- /dev/null +++ b/agrilink_vocpro/lib/features/home/model/latest_data_response.dart @@ -0,0 +1,185 @@ +class LatestDataResponse { + Data? data; + int? statusCode; + String? message; + + LatestDataResponse({this.data, this.statusCode, this.message}); + + LatestDataResponse.fromJson(Map json) { + data = json['data'] != null ? Data.fromJson(json['data']) : null; + statusCode = json['statusCode']; + message = json['message']; + } + + Map toJson() { + final Map data = {}; + if (this.data != null) { + data['data'] = this.data!.toJson(); + } + data['statusCode'] = statusCode; + data['message'] = message; + return data; + } +} + +class Data { + List? dht; + List? npk1; + List? npk2; + + Data({this.dht, this.npk1, this.npk2}); + + Data.fromJson(Map json) { + if (json['dht'] != null) { + dht = []; + json['dht'].forEach((v) { + dht!.add(Dht.fromJson(v)); + }); + } + if (json['npk1'] != null) { + npk1 = []; + json['npk1'].forEach((v) { + npk1!.add(Npk1.fromJson(v)); + }); + } + if (json['npk2'] != null) { + npk2 = []; + json['npk2'].forEach((v) { + npk2!.add(Npk2.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = {}; + if (dht != null) { + data['dht'] = dht!.map((v) => v.toJson()).toList(); + } + if (npk1 != null) { + data['npk1'] = npk1!.map((v) => v.toJson()).toList(); + } + if (npk2 != null) { + data['npk2'] = npk2!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Dht { + int? hour; + num? vicitemperatureAvg; + num? vicihumidityAvg; + num? viciluminosityAvg; + + Dht( + {this.hour, + this.vicitemperatureAvg, + this.vicihumidityAvg, + this.viciluminosityAvg}); + + Dht.fromJson(Map json) { + hour = json['hour']; + vicitemperatureAvg = json['vicitemperature_avg']; + vicihumidityAvg = json['vicihumidity_avg']; + viciluminosityAvg = json['viciluminosity_avg']; + } + + Map toJson() { + final Map data = {}; + data['hour'] = hour; + data['vicitemperature_avg'] = vicitemperatureAvg; + data['vicihumidity_avg'] = vicihumidityAvg; + data['viciluminosity_avg'] = viciluminosityAvg; + return data; + } +} + +class Npk1 { + int? hour; + num? soiltemperatureAvg; + num? soilhumidityAvg; + num? soilconductivityAvg; + num? soilphAvg; + num? soilnitrogenAvg; + num? soilphosphorusAvg; + num? soilpotassiumAvg; + + Npk1( + {this.hour, + this.soiltemperatureAvg, + this.soilhumidityAvg, + this.soilconductivityAvg, + this.soilphAvg, + this.soilnitrogenAvg, + this.soilphosphorusAvg, + this.soilpotassiumAvg}); + + Npk1.fromJson(Map json) { + hour = json['hour']; + soiltemperatureAvg = json['soiltemperature_avg']; + soilhumidityAvg = json['soilhumidity_avg']; + soilconductivityAvg = json['soilconductivity_avg']; + soilphAvg = json['soilph_avg']; + soilnitrogenAvg = json['soilnitrogen_avg']; + soilphosphorusAvg = json['soilphosphorus_avg']; + soilpotassiumAvg = json['soilpotassium_avg']; + } + + Map toJson() { + final Map data = {}; + data['hour'] = hour; + data['soiltemperature_avg'] = soiltemperatureAvg; + data['soilhumidity_avg'] = soilhumidityAvg; + data['soilconductivity_avg'] = soilconductivityAvg; + data['soilph_avg'] = soilphAvg; + data['soilnitrogen_avg'] = soilnitrogenAvg; + data['soilphosphorus_avg'] = soilphosphorusAvg; + data['soilpotassium_avg'] = soilpotassiumAvg; + return data; + } +} + +class Npk2 { + int? hour; + num? soiltemperatureAvg; + num? soilhumidityAvg; + num? soilconductivityAvg; + num? soilphAvg; + num? soilnitrogenAvg; + num? soilphosphorusAvg; + num? soilpotassiumAvg; + + Npk2( + {this.hour, + this.soiltemperatureAvg, + this.soilhumidityAvg, + this.soilconductivityAvg, + this.soilphAvg, + this.soilnitrogenAvg, + this.soilphosphorusAvg, + this.soilpotassiumAvg}); + + Npk2.fromJson(Map json) { + hour = json['hour']; + soiltemperatureAvg = json['soiltemperature_avg']; + soilhumidityAvg = json['soilhumidity_avg']; + soilconductivityAvg = json['soilconductivity_avg']; + soilphAvg = json['soilph_avg']; + soilnitrogenAvg = json['soilnitrogen_avg']; + soilphosphorusAvg = json['soilphosphorus_avg']; + soilpotassiumAvg = json['soilpotassium_avg']; + } + + Map toJson() { + final Map data = {}; + data['hour'] = hour; + data['soiltemperature_avg'] = soiltemperatureAvg; + data['soilhumidity_avg'] = soilhumidityAvg; + data['soilconductivity_avg'] = soilconductivityAvg; + data['soilph_avg'] = soilphAvg; + data['soilnitrogen_avg'] = soilnitrogenAvg; + data['soilphosphorus_avg'] = soilphosphorusAvg; + data['soilpotassium_avg'] = soilpotassiumAvg; + return data; + } +} diff --git a/agrilink_vocpro/lib/features/home/model/npk1_graphic_response.dart b/agrilink_vocpro/lib/features/home/model/npk1_graphic_response.dart new file mode 100644 index 0000000..c159658 --- /dev/null +++ b/agrilink_vocpro/lib/features/home/model/npk1_graphic_response.dart @@ -0,0 +1,91 @@ +class Npk1GraphicResponse { + DataNpk1? data; + int? statusCode; + String? message; + + Npk1GraphicResponse({this.data, this.statusCode, this.message}); + + Npk1GraphicResponse.fromJson(Map json) { + data = json['data'] != null ? DataNpk1.fromJson(json['data']) : null; + statusCode = json['statusCode']; + message = json['message']; + } + + Map toJson() { + final Map data = {}; + if (this.data != null) { + data['data'] = this.data!.toJson(); + } + data['statusCode'] = statusCode; + data['message'] = message; + return data; + } +} + +class DataNpk1 { + List? npk1; + + DataNpk1({this.npk1}); + + DataNpk1.fromJson(Map json) { + if (json['npk1'] != null) { + npk1 = []; + json['npk1'].forEach((v) { + npk1!.add(Npk1.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = {}; + if (npk1 != null) { + data['npk1'] = npk1!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Npk1 { + int? hour; + double? soiltemperatureAvg; + double? soilhumidityAvg; + double? soilconductivityAvg; + double? soilphAvg; + double? soilnitrogenAvg; + double? soilphosphorusAvg; + double? soilpotassiumAvg; + + Npk1( + {this.hour, + this.soiltemperatureAvg, + this.soilhumidityAvg, + this.soilconductivityAvg, + this.soilphAvg, + this.soilnitrogenAvg, + this.soilphosphorusAvg, + this.soilpotassiumAvg}); + + Npk1.fromJson(Map json) { + hour = json['hour']; + soiltemperatureAvg = json['soiltemperature_avg']; + soilhumidityAvg = json['soilhumidity_avg']; + soilconductivityAvg = json['soilconductivity_avg']; + soilphAvg = json['soilph_avg']; + soilnitrogenAvg = json['soilnitrogen_avg']; + soilphosphorusAvg = json['soilphosphorus_avg']; + soilpotassiumAvg = json['soilpotassium_avg']; + } + + Map toJson() { + final Map data = {}; + data['hour'] = hour; + data['soiltemperature_avg'] = soiltemperatureAvg; + data['soilhumidity_avg'] = soilhumidityAvg; + data['soilconductivity_avg'] = soilconductivityAvg; + data['soilph_avg'] = soilphAvg; + data['soilnitrogen_avg'] = soilnitrogenAvg; + data['soilphosphorus_avg'] = soilphosphorusAvg; + data['soilpotassium_avg'] = soilpotassiumAvg; + return data; + } +} diff --git a/agrilink_vocpro/lib/features/home/model/npk1_soil_temp_grafik.dart b/agrilink_vocpro/lib/features/home/model/npk1_soil_temp_grafik.dart new file mode 100644 index 0000000..6877233 --- /dev/null +++ b/agrilink_vocpro/lib/features/home/model/npk1_soil_temp_grafik.dart @@ -0,0 +1,65 @@ +class Npk1SoilTempGrafik { + Data? data; + int? statusCode; + String? message; + + Npk1SoilTempGrafik({this.data, this.statusCode, this.message}); + + Npk1SoilTempGrafik.fromJson(Map json) { + data = json['data'] != null ? Data.fromJson(json['data']) : null; + statusCode = json['statusCode']; + message = json['message']; + } + + Map toJson() { + final Map data = {}; + if (this.data != null) { + data['data'] = this.data!.toJson(); + } + data['statusCode'] = statusCode; + data['message'] = message; + return data; + } +} + +class Data { + List? npk1; + + Data({this.npk1}); + + Data.fromJson(Map json) { + if (json['npk1'] != null) { + npk1 = []; + json['npk1'].forEach((v) { + npk1!.add(Npk1.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = {}; + if (npk1 != null) { + data['npk1'] = npk1!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Npk1 { + num? hour; + num? soiltemperatureAvg; + + Npk1({this.hour, this.soiltemperatureAvg}); + + Npk1.fromJson(Map json) { + hour = json['hour']; + soiltemperatureAvg = json['soiltemperature_avg']; + } + + Map toJson() { + final Map data = {}; + data['hour'] = hour; + data['soiltemperature_avg'] = soiltemperatureAvg; + return data; + } +} diff --git a/agrilink_vocpro/lib/features/home/model/npk2_graphic_response.dart b/agrilink_vocpro/lib/features/home/model/npk2_graphic_response.dart new file mode 100644 index 0000000..58302a3 --- /dev/null +++ b/agrilink_vocpro/lib/features/home/model/npk2_graphic_response.dart @@ -0,0 +1,91 @@ +class Npk2GraphicResponse { + DataNpk2? data; + int? statusCode; + String? message; + + Npk2GraphicResponse({this.data, this.statusCode, this.message}); + + Npk2GraphicResponse.fromJson(Map json) { + data = json['data'] != null ? DataNpk2.fromJson(json['data']) : null; + statusCode = json['statusCode']; + message = json['message']; + } + + Map toJson() { + final Map data = {}; + if (this.data != null) { + data['data'] = this.data!.toJson(); + } + data['statusCode'] = statusCode; + data['message'] = message; + return data; + } +} + +class DataNpk2 { + List? npk2; + + DataNpk2({this.npk2}); + + DataNpk2.fromJson(Map json) { + if (json['npk2'] != null) { + npk2 = []; + json['npk2'].forEach((v) { + npk2!.add(Npk2.fromJson(v)); + }); + } + } + + Map toJson() { + final Map data = {}; + if (npk2 != null) { + data['npk2'] = npk2!.map((v) => v.toJson()).toList(); + } + return data; + } +} + +class Npk2 { + int? hour; + double? soiltemperatureAvg; + double? soilhumidityAvg; + double? soilconductivityAvg; + double? soilphAvg; + double? soilnitrogenAvg; + double? soilphosphorusAvg; + double? soilpotassiumAvg; + + Npk2( + {this.hour, + this.soiltemperatureAvg, + this.soilhumidityAvg, + this.soilconductivityAvg, + this.soilphAvg, + this.soilnitrogenAvg, + this.soilphosphorusAvg, + this.soilpotassiumAvg}); + + Npk2.fromJson(Map json) { + hour = json['hour']; + soiltemperatureAvg = json['soiltemperature_avg']; + soilhumidityAvg = json['soilhumidity_avg']; + soilconductivityAvg = json['soilconductivity_avg']; + soilphAvg = json['soilph_avg']; + soilnitrogenAvg = json['soilnitrogen_avg']; + soilphosphorusAvg = json['soilphosphorus_avg']; + soilpotassiumAvg = json['soilpotassium_avg']; + } + + Map toJson() { + final Map data = {}; + data['hour'] = hour; + data['soiltemperature_avg'] = soiltemperatureAvg; + data['soilhumidity_avg'] = soilhumidityAvg; + data['soilconductivity_avg'] = soilconductivityAvg; + data['soilph_avg'] = soilphAvg; + data['soilnitrogen_avg'] = soilnitrogenAvg; + data['soilphosphorus_avg'] = soilphosphorusAvg; + data['soilpotassium_avg'] = soilpotassiumAvg; + return data; + } +} diff --git a/agrilink_vocpro/lib/features/home/pages/humidity/view/humidity_screen.dart b/agrilink_vocpro/lib/features/home/pages/humidity/view/humidity_screen.dart index b3d9cb6..7a8ca86 100644 --- a/agrilink_vocpro/lib/features/home/pages/humidity/view/humidity_screen.dart +++ b/agrilink_vocpro/lib/features/home/pages/humidity/view/humidity_screen.dart @@ -54,7 +54,7 @@ class HumidityScreen extends StatelessWidget { children: [ const Icon(BootstrapIcons.droplet_half, size: 32, color: Colors.blue), - Text('60 %', style: AppTheme.headline1), + Text('$humidity %', style: AppTheme.headline1), ], ), ), @@ -63,7 +63,7 @@ class HumidityScreen extends StatelessWidget { child: AnimatedRadialGauge( duration: const Duration(seconds: 3), curve: Curves.easeOut, - value: 60, + value: humidity, axis: GaugeAxis( degrees: 360, min: 0, diff --git a/agrilink_vocpro/lib/features/home/pages/soil_moisture/view/soil_moisture_screen.dart b/agrilink_vocpro/lib/features/home/pages/soil_moisture/view/soil_moisture_screen.dart index c05a466..7b2fdc0 100644 --- a/agrilink_vocpro/lib/features/home/pages/soil_moisture/view/soil_moisture_screen.dart +++ b/agrilink_vocpro/lib/features/home/pages/soil_moisture/view/soil_moisture_screen.dart @@ -50,7 +50,7 @@ class SoilMoistureScreen extends StatelessWidget { children: [ const Icon(BootstrapIcons.water, size: 32, color: Colors.blue), - Text('60 %', style: AppTheme.headline1), + Text('$moisture %', style: AppTheme.headline1), ], ), ), diff --git a/agrilink_vocpro/lib/features/home/pages/soil_temperature/provider/soil_temp_provider.dart b/agrilink_vocpro/lib/features/home/pages/soil_temperature/provider/soil_temp_provider.dart new file mode 100644 index 0000000..85098c3 --- /dev/null +++ b/agrilink_vocpro/lib/features/home/pages/soil_temperature/provider/soil_temp_provider.dart @@ -0,0 +1,47 @@ +import 'package:agrilink_vocpro/core/state/result_state.dart'; +import 'package:agrilink_vocpro/features/home/model/npk1_soil_temp_grafik.dart'; +import 'package:agrilink_vocpro/features/home/service/home_service.dart'; +import 'package:flutter/material.dart'; + +class SoilTempProvider extends ChangeNotifier { + SoilTempProvider() { + getSoilTempData(); + } + + List dataFetched = []; + + void setSoilTempData(List data) { + dataFetched = data; + notifyListeners(); + } + + ResultState dataState = ResultState.initial; + + Future getSoilTempData() async { + dataState = ResultState.loading; + notifyListeners(); + try { + final result = await HomeService().getNpk1SoilTempGrafik(); + if (result.data == null || result.data!.npk1!.isEmpty) { + dataState = ResultState.noData; + notifyListeners(); + return; + } else { + setSoilTempData(result.data?.npk1 ?? []); + dataState = ResultState.hasData; + notifyListeners(); + } + } catch (e) { + print('Error: $e'); + dataState = ResultState.error; + notifyListeners(); + } + } + + @override + void dispose() { + dataState = ResultState.initial; + dataFetched = []; + super.dispose(); + } +} diff --git a/agrilink_vocpro/lib/features/home/pages/soil_temperature/view/soil_temperature_screen.dart b/agrilink_vocpro/lib/features/home/pages/soil_temperature/view/soil_temperature_screen.dart index 6715b63..ccc10a2 100644 --- a/agrilink_vocpro/lib/features/home/pages/soil_temperature/view/soil_temperature_screen.dart +++ b/agrilink_vocpro/lib/features/home/pages/soil_temperature/view/soil_temperature_screen.dart @@ -1,11 +1,14 @@ import 'package:agrilink_vocpro/core/constant/app_constant.dart'; import 'package:agrilink_vocpro/core/constant/app_theme.dart'; +import 'package:agrilink_vocpro/core/state/result_state.dart'; import 'package:agrilink_vocpro/core/widgets/show_info.dart'; +import 'package:agrilink_vocpro/features/home/pages/soil_temperature/provider/soil_temp_provider.dart'; import 'package:agrilink_vocpro/features/home/widgets/graphic_widget.dart'; import 'package:bootstrap_icons/bootstrap_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:gauge_indicator/gauge_indicator.dart'; +import 'package:provider/provider.dart'; class SoilTemperatureScreen extends StatelessWidget { const SoilTemperatureScreen({super.key, this.temperature = 0}); @@ -15,218 +18,269 @@ class SoilTemperatureScreen extends StatelessWidget { @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text('Soil Temperature', style: AppTheme.labelMedium), - centerTitle: true, - backgroundColor: Colors.white, - scrolledUnderElevation: 0, - actions: const [ - Padding( - padding: EdgeInsets.only(right: 16), - child: Icon( - BootstrapIcons.water, - color: Colors.green, - ), - ) - ], - ), - body: SafeArea( - child: ListView( - padding: EdgeInsets.all(16.w), - children: [ - SizedBox( - height: MediaQuery.of(context).size.height * 0.05, - ), - SizedBox( - height: 240.h, - child: Stack( - fit: StackFit.expand, - children: [ - Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - height: 80.h, - ), - const Icon(BootstrapIcons.water, - size: 32, color: Colors.green), - Text( - '${value.toStringAsFixed(0)}°C', // Animated percentage text - style: const TextStyle( - fontSize: 28, - fontWeight: FontWeight.bold, - color: Colors.black, + return ChangeNotifierProvider( + create: (context) => SoilTempProvider(), + child: Scaffold( + appBar: AppBar( + title: Text('Soil Temperature', style: AppTheme.labelMedium), + centerTitle: true, + backgroundColor: Colors.white, + scrolledUnderElevation: 0, + actions: const [ + Padding( + padding: EdgeInsets.only(right: 16), + child: Icon( + BootstrapIcons.water, + color: Colors.green, + ), + ) + ], + ), + body: SafeArea( + child: ListView( + padding: EdgeInsets.all(16.w), + children: [ + SizedBox( + height: MediaQuery.of(context).size.height * 0.05, + ), + SizedBox( + height: 240.h, + child: Stack( + fit: StackFit.expand, + children: [ + Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 80.h, ), + const Icon(BootstrapIcons.water, + size: 32, color: Colors.green), + Text( + '$value°C', // Animated percentage text + style: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: Colors.black, + ), + ), + ], + ), + ), + AnimatedRadialGauge( + duration: const Duration(seconds: 2), + curve: Curves.easeOut, + value: value, + axis: GaugeAxis( + degrees: 240, + min: 0, + max: 56.7, + style: GaugeAxisStyle( + background: Colors.grey.shade100, + thickness: 50, + ), + progressBar: const GaugeBasicProgressBar( + gradient: GaugeAxisGradient(colors: [ + Colors.blue, + Colors.orange, + ]), + ), + ), + ), + ], + ), + ), + 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), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Container( + height: 100.h, + width: 100.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16), + color: Colors.blue.withOpacity(0.1), + border: Border.all( + color: Colors.blue, + width: 2, + ), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('Low', + style: AppTheme.labelMedium + .copyWith(color: Colors.blue)), + SizedBox(height: 8.h), + Text( + '<20°C', + style: AppTheme.labelMedium, + textAlign: TextAlign.center, ), ], ), ), - AnimatedRadialGauge( - duration: const Duration(seconds: 2), - curve: Curves.easeOut, - value: value, - axis: GaugeAxis( - degrees: 240, - min: 0, - max: 56.7, - style: GaugeAxisStyle( - background: Colors.grey.shade100, - thickness: 50, + Container( + height: 100.h, + width: 100.w, + decoration: BoxDecoration( + color: Colors.green.withOpacity(0.1), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: Colors.green, + width: 2, ), - progressBar: const GaugeBasicProgressBar( - gradient: GaugeAxisGradient(colors: [ - Colors.blue, - Colors.orange, - ]), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('Ideal', + style: AppTheme.labelMedium + .copyWith(color: Colors.green)), + // SizedBox(height: 8.h), + // const Icon( + // BootstrapIcons.thermometer_half, + // color: Colors.green, + // ), + SizedBox(height: 8.h), + Text( + '20-30°C', + style: AppTheme.labelMedium, + textAlign: TextAlign.center, + ), + ], + ), + ), + Container( + height: 100.h, + width: 100.w, + decoration: BoxDecoration( + color: Colors.orange.withOpacity(0.1), + borderRadius: BorderRadius.circular(16), + border: Border.all( + color: Colors.orange.shade800, + width: 2, ), ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('high', + style: AppTheme.labelMedium + .copyWith(color: Colors.orange)), + SizedBox(height: 8.h), + Text( + '>30°C', + style: AppTheme.labelMedium, + textAlign: TextAlign.center, + ), + ], + ), ), ], ), - ), - 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), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - Container( - height: 100.h, - width: 100.w, + SizedBox(height: 16.h), + const Text('Grafik'), + SizedBox(height: 16.h), + AspectRatio( + aspectRatio: 1.6.h, + child: Container( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(16), - color: Colors.blue.withOpacity(0.1), - border: Border.all( - color: Colors.blue, - width: 2, - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('Low', - style: AppTheme.labelMedium - .copyWith(color: Colors.blue)), - // SizedBox(height: 8.h), - // const Icon( - // BootstrapIcons.thermometer_low, - // color: Colors.blue, - // ), - SizedBox(height: 8.h), - Text( - '<20°C', - style: AppTheme.labelMedium, - textAlign: TextAlign.center, - ), - ], + color: Colors.white, + borderRadius: BorderRadius.circular(16.w), + border: Border.all(color: Colors.grey.shade300, width: 1.w), ), + child: Consumer( + builder: (context, provider, child) { + switch (provider.dataState) { + case ResultState.loading: + return const Center( + child: CircularProgressIndicator(), + ); + case ResultState.hasData: + return GarphicWidget( + gradientColors: const [ + Colors.cyan, + Colors.amber, + ], + hour: List.generate(provider.dataFetched.length, + (index) => provider.dataFetched[index].hour ?? 0), + data: List.generate( + provider.dataFetched.length, + (index) => + provider.dataFetched[index].soiltemperatureAvg + ?.toDouble() ?? + 0), + ); + case ResultState.error: + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + BootstrapIcons.exclamation_circle, + color: Colors.grey.shade400, + ), + SizedBox(height: 8.h), + Text( + 'Terjadi Kesalahan', + style: AppTheme.labelSmall, + ), + ], + ), + ); + case ResultState.noData: + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + BootstrapIcons.database_fill_x, + color: Colors.grey.shade400, + ), + SizedBox(height: 8.h), + Text( + 'Tidak Ada Data', + style: AppTheme.labelSmall, + ), + ], + ), + ); + case ResultState.initial: + return const SizedBox.shrink(); + default: + return const Center( + child: Text('Default Error'), + ); + } + }), ), - Container( - height: 100.h, - width: 100.w, - decoration: BoxDecoration( - color: Colors.green.withOpacity(0.1), - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: Colors.green, - width: 2, - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('Ideal', - style: AppTheme.labelMedium - .copyWith(color: Colors.green)), - // SizedBox(height: 8.h), - // const Icon( - // BootstrapIcons.thermometer_half, - // color: Colors.green, - // ), - SizedBox(height: 8.h), - Text( - '20-30°C', - style: AppTheme.labelMedium, - textAlign: TextAlign.center, - ), - ], - ), - ), - Container( - height: 100.h, - width: 100.w, - decoration: BoxDecoration( - color: Colors.orange.withOpacity(0.1), - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: Colors.orange.shade800, - width: 2, - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('high', - style: AppTheme.labelMedium - .copyWith(color: Colors.orange)), - // SizedBox(height: 8.h), - // const Icon( - // BootstrapIcons.thermometer_high, - // color: Colors.orange, - // ), - SizedBox(height: 8.h), - Text( - '>30°C', - style: AppTheme.labelMedium, - textAlign: TextAlign.center, - ), - ], - ), - ), - ], - ), - SizedBox(height: 16.h), - const Text('Grafik'), - SizedBox(height: 16.h), - AspectRatio( - aspectRatio: 1.6.h, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(16.w), - border: Border.all(color: Colors.grey.shade300, width: 1.w), - ), - child: const GarphicWidget( - gradientColors: [ - Colors.cyan, - Colors.amber, - ], - ), - ), - ) - ], + ) + ], + ), ), ), ); diff --git a/agrilink_vocpro/lib/features/home/provider/home_provider.dart b/agrilink_vocpro/lib/features/home/provider/home_provider.dart index 12a161c..1c749c4 100644 --- a/agrilink_vocpro/lib/features/home/provider/home_provider.dart +++ b/agrilink_vocpro/lib/features/home/provider/home_provider.dart @@ -1,25 +1,101 @@ import 'package:agrilink_vocpro/core/state/result_state.dart'; +import 'package:agrilink_vocpro/domain/service/app_service.dart'; import 'package:flutter/material.dart'; class HomeProvider extends ChangeNotifier { final DateTime currentDate = DateTime.now(); + num _dhtHumidity = 0; + num get dhtHumidity => _dhtHumidity; + + num _dhtTemperature = 0; + num get dhtTemperature => _dhtTemperature; + + num _dhtLuminosity = 0; + num get dhtLuminosity => _dhtLuminosity; + + num _npk1SoilMoisture = 0; + num get npk1SoilMoisture => _npk1SoilMoisture; + + num _npk1Temperature = 0; + num get npk1Temperature => _npk1Temperature; + + num _npk1SoilPh = 0; + num get npk1SoilPh => _npk1SoilPh; + + num _npk1SoilEc = 0; + num get npk1SoilEc => _npk1SoilEc; + + num _npk1SoilNitrogen = 0; + num get npk1SoilNitrogen => _npk1SoilNitrogen; + + num _npk1SoilPhosphorus = 0; + num get npk1SoilPhosphorus => _npk1SoilPhosphorus; + + num _npk1SoilPotassium = 0; + num get npk1SoilPotassium => _npk1SoilPotassium; + + num _npk2SoilMoisture = 0; + num get npk2SoilMoisture => _npk2SoilMoisture; + + num _npk2Temperature = 0; + num get npk2Temperature => _npk2Temperature; + + num _npk2SoilPh = 0; + num get npk2SoilPh => _npk2SoilPh; + + num _npk2SoilEc = 0; + num get npk2SoilEc => _npk2SoilEc; + + num _npk2SoilNitrogen = 0; + num get npk2SoilNitrogen => _npk2SoilNitrogen; + + num _npk2SoilPhosphorus = 0; + num get npk2SoilPhosphorus => _npk2SoilPhosphorus; + + num _npk2SoilPotassium = 0; + num get npk2SoilPotassium => _npk2SoilPotassium; + HomeProvider() { - getData(); + getLatestData(); } ResultState dataState = ResultState.initial; - Future getData() async { + Future getLatestData() async { dataState = ResultState.loading; notifyListeners(); try { - print('Fetching data...'); - await Future.delayed(const Duration(seconds: 3)); - print('Data fetched'); - dataState = ResultState.hasData; - notifyListeners(); + final result = await AppService().getLatestData(); + if (result.data == null) { + dataState = ResultState.noData; + notifyListeners(); + } else { + final data = result.data!; + _dhtHumidity = data.dht?[0].vicihumidityAvg ?? 0; + _dhtTemperature = data.dht?[0].vicitemperatureAvg ?? 0; + _dhtLuminosity = data.dht?[0].viciluminosityAvg ?? 0; + + _npk1SoilMoisture = data.npk1?[0].soilhumidityAvg ?? 0; + _npk1Temperature = data.npk1?[0].soiltemperatureAvg ?? 0; + _npk1SoilPh = data.npk1?[0].soilphAvg ?? 0; + _npk1SoilEc = data.npk1?[0].soilconductivityAvg ?? 0; + _npk1SoilNitrogen = data.npk1?[0].soilnitrogenAvg ?? 0; + _npk1SoilPhosphorus = data.npk1?[0].soilphosphorusAvg ?? 0; + _npk1SoilPotassium = data.npk1?[0].soilpotassiumAvg ?? 0; + + _npk2SoilMoisture = data.npk2?[0].soilhumidityAvg ?? 0; + _npk2Temperature = data.npk2?[0].soiltemperatureAvg ?? 0; + _npk2SoilPh = data.npk2?[0].soilphAvg ?? 0; + _npk2SoilEc = data.npk2?[0].soilconductivityAvg ?? 0; + _npk2SoilNitrogen = data.npk2?[0].soilnitrogenAvg ?? 0; + _npk2SoilPhosphorus = data.npk2?[0].soilphosphorusAvg ?? 0; + _npk2SoilPotassium = data.npk2?[0].soilpotassiumAvg ?? 0; + dataState = ResultState.hasData; + notifyListeners(); + } } catch (e) { + print('Error: $e'); dataState = ResultState.error; notifyListeners(); } @@ -31,57 +107,3 @@ class HomeProvider extends ChangeNotifier { super.dispose(); } } - - - // List humidtyRules = [ - // CensorDataRule( - // minPercentage: 0, - // maxPercentage: 30, - // censorText: 'Very Low', - // description: - // 'Udara sangat kering. Tanaman bisa mengalami stress akibat kekurangan air.', - // action: - // 'Aktifkan sistem penyiraman atau humidifier untuk menaikkan kelembaban. Periksa juga apakah ada kebocoran pada sistem irigasi yang mengakibatkan kelembaban terlalu rendah.', - // color: Colors.red, - // ), - // CensorDataRule( - // minPercentage: 31, - // maxPercentage: 50, - // censorText: 'Low', - // description: - // 'Kelembaban masih cukup rendah. Beberapa jenis tanaman mungkin sudah mulai terpengaruh.', - // action: - // 'Pertimbangkan untuk menambah irigasi atau memperpanjang durasi penyiraman. Pantau tanaman secara berkala.', - // color: Colors.orange, - // ), - // CensorDataRule( - // minPercentage: 51, - // maxPercentage: 70, - // censorText: 'Normal', - // description: - // 'Ini adalah kelembaban yang ideal untuk sebagian besar tanaman dalam greenhouse.', - // action: - // 'Pertahankan kondisi ini. Tidak ada tindakan yang diperlukan kecuali jika ada perubahan mendadak.', - // color: Colors.green, - // ), - // CensorDataRule( - // minPercentage: 71, - // maxPercentage: 85, - // censorText: 'High', - // description: - // 'Udara mulai terlalu lembap. Kelembaban tinggi dapat meningkatkan risiko penyakit jamur atau bakteri.', - // action: - // 'Aktifkan ventilasi atau kipas untuk mengurangi kelembaban. Pastikan aliran udara di greenhouse cukup baik.', - // color: Colors.lime, - // ), - // CensorDataRule( - // minPercentage: 86, - // maxPercentage: 100, - // censorText: 'Very High', - // description: - // 'Udara sangat lembap, yang bisa berisiko menyebabkan jamur, lumut, dan penyakit tanaman.', - // action: - // 'Segera aktifkan sistem ventilasi maksimal, mungkin juga gunakan dehumidifier jika diperlukan. Kurangi frekuensi penyiraman atau periksa sistem irigasi agar tidak berlebihan.', - // color: Colors.brown, - // ), - // ]; diff --git a/agrilink_vocpro/lib/features/home/service/home_service.dart b/agrilink_vocpro/lib/features/home/service/home_service.dart new file mode 100644 index 0000000..fa5a71e --- /dev/null +++ b/agrilink_vocpro/lib/features/home/service/home_service.dart @@ -0,0 +1,29 @@ +import 'package:agrilink_vocpro/core/constant/app_constant.dart'; +import 'package:agrilink_vocpro/features/home/model/npk1_soil_temp_grafik.dart'; +import 'package:dio/dio.dart'; + +class HomeService { + final Dio _dioWithoutInterceptor = Dio( + BaseOptions( + baseUrl: AppConstant.baseUrl, + ), + ); + + Future getNpk1SoilTempGrafik() async { + try { + final result = await _dioWithoutInterceptor.get( + '/sensor/getData?metric=soilTemperature&range[start]=2024-10-03&range[end]=2024-10-03&range[time_range]=HOURLY&sensor=npk1', + ); + if (result.statusCode == 200) { + print(result.data.toString()); + final data = Npk1SoilTempGrafik.fromJson(result.data); + return data; + } else { + throw Exception('Failed to load data'); + } + } on DioException catch (e) { + print(e); + rethrow; + } + } +} diff --git a/agrilink_vocpro/lib/features/home/view/home_screen.dart b/agrilink_vocpro/lib/features/home/view/home_screen.dart index 224cadc..f25dcd5 100644 --- a/agrilink_vocpro/lib/features/home/view/home_screen.dart +++ b/agrilink_vocpro/lib/features/home/view/home_screen.dart @@ -60,7 +60,7 @@ class _HomeScreenState extends State { const Spacer(), IconButton( onPressed: () { - context.read().getData(); + context.read().getLatestData(); }, icon: const Icon( Icons.refresh_rounded, diff --git a/agrilink_vocpro/lib/features/home/widgets/graphic_widget.dart b/agrilink_vocpro/lib/features/home/widgets/graphic_widget.dart index 2660ba8..da1b498 100644 --- a/agrilink_vocpro/lib/features/home/widgets/graphic_widget.dart +++ b/agrilink_vocpro/lib/features/home/widgets/graphic_widget.dart @@ -4,10 +4,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; class GarphicWidget extends StatelessWidget { - const GarphicWidget({super.key, required this.gradientColors}); + const GarphicWidget( + {super.key, required this.gradientColors, this.data, this.hour}); final List gradientColors; - + final List? hour; + final List? data; @override Widget build(BuildContext context) { return Padding( @@ -48,6 +50,16 @@ class GarphicWidget extends StatelessWidget { ); } + int getMaxValue() { + int max = 0; + for (int i = 0; i < data!.length; i++) { + if (data![i] > max) { + max = data![i].toInt(); + } + } + return max; + } + LineChartData mainData() { return LineChartData( gridData: const FlGridData( @@ -80,18 +92,16 @@ class GarphicWidget extends StatelessWidget { minX: 0, maxX: 24, minY: 0, - maxY: 100, + maxY: data == null ? 0 : getMaxValue().toDouble(), lineBarsData: [ LineChartBarData( - spots: const [ - FlSpot(0, 38), - FlSpot(1, 42), - FlSpot(2, 50), - FlSpot(3, 53), - FlSpot(4, 58), - FlSpot(5, 64), - FlSpot(7, 49), - ], + spots: data == null && hour == null + ? [FlSpot(0, 0)] + : List.generate( + hour!.length, + (index) => + FlSpot(hour![index].toDouble(), data![index].toDouble()), + ), isCurved: true, gradient: LinearGradient( colors: gradientColors, diff --git a/agrilink_vocpro/lib/features/home/widgets/list_data_from_censor_dht.dart b/agrilink_vocpro/lib/features/home/widgets/list_data_from_censor_dht.dart index 628ca9d..740b38d 100644 --- a/agrilink_vocpro/lib/features/home/widgets/list_data_from_censor_dht.dart +++ b/agrilink_vocpro/lib/features/home/widgets/list_data_from_censor_dht.dart @@ -50,7 +50,7 @@ class ListDataFromCensorDht extends StatelessWidget { DataDisplayerWidget( title: 'Humidity', subtitle: 'kelembaban udara', - value: '60', + value: provider.dhtHumidity.toString(), unit: '%', icon: BootstrapIcons.droplet_half, textColor: Colors.white, @@ -58,29 +58,32 @@ class ListDataFromCensorDht extends StatelessWidget { iconColor: Colors.white, censorIdentifier: 'NPK 1', onTap: () async { - await context.push('${AppRoute.humidity}/60'); + await context + .push('${AppRoute.humidity}/${provider.dhtHumidity}'); }, ), DataDisplayerWidget( title: 'Temperature', subtitle: 'suhu greenhouse', - value: '43', + value: provider.dhtTemperature.toString(), unit: '°C', icon: BootstrapIcons.thermometer_half, color: Colors.white, onTap: () async { - await context.push('${AppRoute.temperature}/43'); + await context.push( + '${AppRoute.temperature}/${provider.dhtTemperature}'); }, ), DataDisplayerWidget( title: 'Light', subtitle: 'intensitas cahaya', - value: '320.5', + value: provider.dhtLuminosity.toString(), unit: 'lux', icon: BootstrapIcons.sun, color: Colors.white, onTap: () async { - await context.push('${AppRoute.light}/320.5'); + await context + .push('${AppRoute.light}/${provider.dhtLuminosity}'); }, ), ], diff --git a/agrilink_vocpro/lib/features/home/widgets/list_data_from_censor_npk1.dart b/agrilink_vocpro/lib/features/home/widgets/list_data_from_censor_npk1.dart index 0249cdd..b60b491 100644 --- a/agrilink_vocpro/lib/features/home/widgets/list_data_from_censor_npk1.dart +++ b/agrilink_vocpro/lib/features/home/widgets/list_data_from_censor_npk1.dart @@ -49,7 +49,7 @@ class ListDataFromCensorNpk1 extends StatelessWidget { DataDisplayerWidget( title: 'Temperature', subtitle: 'Suhu tanah', - value: '28', + value: provider.npk1Temperature.toString(), unit: '°C', icon: BootstrapIcons.thermometer_half, textColor: Colors.white, @@ -57,76 +57,82 @@ class ListDataFromCensorNpk1 extends StatelessWidget { iconColor: Colors.white, censorIdentifier: censorIdentifier, onTap: () async { - await context.push('${AppRoute.soilTemperature}/28'); + await context.push( + '${AppRoute.soilTemperature}/${provider.npk1Temperature}'); }, ), DataDisplayerWidget( title: 'Soil Moisture', subtitle: 'kelembaban tanah', - value: '40', + value: provider.npk1SoilMoisture.toString(), unit: '%', icon: Icons.water_outlined, color: Colors.white, censorIdentifier: censorIdentifier, onTap: () async { - await context.push('${AppRoute.soilMoisture}/40'); + await context.push( + '${AppRoute.soilMoisture}/${provider.npk1SoilMoisture}'); }, ), DataDisplayerWidget( title: 'Acid Level (PH)', subtitle: 'tingkat keasaman', - value: '6.5', + value: provider.npk1SoilPh.toString(), unit: 'pH', icon: BootstrapIcons.pie_chart, color: Colors.white, censorIdentifier: censorIdentifier, - onTap: () { - context.push('${AppRoute.ph}/6.5'); + onTap: () async { + context.push('${AppRoute.ph}/${provider.npk1SoilPh}'); }, ), DataDisplayerWidget( title: 'Conductivity', subtitle: 'Daya Arus Listrik', - value: '234', + value: provider.npk1SoilEc.toString(), unit: 'µS/cm', icon: Icons.electric_bolt, color: Colors.white, censorIdentifier: censorIdentifier, onTap: () async { - await context.push('${AppRoute.conductivity}/234'); + await context + .push('${AppRoute.conductivity}/${provider.npk1SoilEc}'); }, ), DataDisplayerWidget( title: 'Nitrogen', subtitle: 'Kadar Nitrogen', - value: '30', + value: provider.npk1SoilNitrogen.toString(), unit: 'ppm', icon: CupertinoIcons.eyedropper, color: Colors.white, onTap: () async { - await context.push('${AppRoute.nitrogen}/30'); + await context.push( + '${AppRoute.nitrogen}/${provider.npk1SoilNitrogen}'); }, ), DataDisplayerWidget( title: 'Potassium', subtitle: 'Kadar kalium', - value: '20', + value: provider.npk1SoilPotassium.toString(), unit: 'ppm', icon: CupertinoIcons.eyedropper, color: Colors.white, onTap: () async { - await context.push('${AppRoute.potassium}/20'); + await context.push( + '${AppRoute.potassium}/${provider.npk1SoilPotassium}'); }, ), DataDisplayerWidget( title: 'Phosphorus', subtitle: 'Kadar Fosfor', - value: '54', + value: provider.npk1SoilPhosphorus.toString(), unit: 'ppm', icon: CupertinoIcons.eyedropper, color: Colors.white, onTap: () async { - await context.push('${AppRoute.phosphorus}/54'); + await context.push( + '${AppRoute.phosphorus}/${provider.npk1SoilPhosphorus}'); }, ), ], diff --git a/agrilink_vocpro/lib/features/home/widgets/list_data_from_censor_npk2.dart b/agrilink_vocpro/lib/features/home/widgets/list_data_from_censor_npk2.dart index c59a3c4..9fb46a4 100644 --- a/agrilink_vocpro/lib/features/home/widgets/list_data_from_censor_npk2.dart +++ b/agrilink_vocpro/lib/features/home/widgets/list_data_from_censor_npk2.dart @@ -1,8 +1,6 @@ import 'package:agrilink_vocpro/core/constant/app_color.dart'; import 'package:agrilink_vocpro/core/route/app_route.dart'; import 'package:agrilink_vocpro/core/state/result_state.dart'; -import 'package:agrilink_vocpro/features/home/pages/soil_moisture/view/soil_moisture_screen.dart'; -import 'package:agrilink_vocpro/features/home/pages/temperature/view/temperature_screen.dart'; import 'package:agrilink_vocpro/features/home/provider/home_provider.dart'; import 'package:agrilink_vocpro/features/home/widgets/censor_item_loading_widgets.dart'; import 'package:agrilink_vocpro/features/home/widgets/data_display_widget.dart'; @@ -51,7 +49,7 @@ class ListDataFromCensorNpk2 extends StatelessWidget { DataDisplayerWidget( title: 'Temperature', subtitle: 'Suhu tanah', - value: '28', + value: provider.npk2Temperature.toString(), unit: '°C', icon: BootstrapIcons.thermometer_half, textColor: Colors.white, @@ -59,77 +57,83 @@ class ListDataFromCensorNpk2 extends StatelessWidget { iconColor: Colors.white, censorIdentifier: censorIdentifier, onTap: () async { - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const TemperatureScreen())); + await context.push( + '${AppRoute.soilTemperature}/${provider.npk2Temperature}'); }, ), DataDisplayerWidget( title: 'Soil Moisture', subtitle: 'kelembaban tanah', - value: '40', + value: provider.npk2SoilMoisture.toString(), unit: '%', icon: Icons.water_outlined, color: Colors.white, censorIdentifier: censorIdentifier, onTap: () async { - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const SoilMoistureScreen(), - ), - ); + await context.push( + '${AppRoute.soilMoisture}/${provider.npk2SoilMoisture}'); }, ), DataDisplayerWidget( title: 'Acid Level (PH)', subtitle: 'tingkat keasaman', - value: '6.5', + value: provider.npk2SoilPh.toString(), unit: 'pH', icon: BootstrapIcons.pie_chart, color: Colors.white, censorIdentifier: censorIdentifier, - onTap: () {}, + onTap: () async { + context.push('${AppRoute.ph}/${provider.npk2SoilPh}'); + }, ), DataDisplayerWidget( title: 'Conductivity', subtitle: 'Daya Arus Listrik', - value: '234', + value: provider.npk2SoilEc.toString(), unit: 'µS/cm', icon: Icons.electric_bolt, color: Colors.white, censorIdentifier: censorIdentifier, onTap: () async { - context.push(AppRoute.humidity, extra: '60'); + await context + .push('${AppRoute.conductivity}/${provider.npk2SoilEc}'); }, ), DataDisplayerWidget( title: 'Nitrogen', subtitle: 'Kadar Nitrogen', - value: '30', + value: provider.npk2SoilNitrogen.toString(), unit: 'ppm', icon: CupertinoIcons.eyedropper, color: Colors.white, - onTap: () {}, + onTap: () async { + await context.push( + '${AppRoute.nitrogen}/${provider.npk2SoilNitrogen}'); + }, ), DataDisplayerWidget( title: 'Potassium', subtitle: 'Kadar kalium', - value: '20', + value: provider.npk2SoilPotassium.toString(), unit: 'ppm', icon: CupertinoIcons.eyedropper, color: Colors.white, - onTap: () {}, + onTap: () async { + await context.push( + '${AppRoute.potassium}/${provider.npk2SoilPotassium}'); + }, ), DataDisplayerWidget( title: 'Phosphorus', subtitle: 'Kadar Fosfor', - value: '54', + value: provider.npk2SoilPhosphorus.toString(), unit: 'ppm', icon: CupertinoIcons.eyedropper, color: Colors.white, - onTap: () {}, + onTap: () async { + await context.push( + '${AppRoute.phosphorus}/${provider.npk2SoilPhosphorus}'); + }, ), ], ); diff --git a/agrilink_vocpro/pubspec.lock b/agrilink_vocpro/pubspec.lock index 58cead9..bba9259 100644 --- a/agrilink_vocpro/pubspec.lock +++ b/agrilink_vocpro/pubspec.lock @@ -141,10 +141,10 @@ packages: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" fl_chart: dependency: "direct main" description: @@ -162,10 +162,10 @@ packages: dependency: "direct dev" description: name: flutter_lints - sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" + sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" flutter_screenutil: dependency: "direct main" description: @@ -196,10 +196,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: "2ddb88e9ad56ae15ee144ed10e33886777eb5ca2509a914850a5faa7b52ff459" + sha256: "6f1b756f6e863259a99135ff3c95026c3cdca17d10ebef2bba2261a25ddc8bbc" url: "https://pub.dev" source: hosted - version: "14.2.7" + version: "14.3.0" google_fonts: dependency: "direct main" description: @@ -268,10 +268,10 @@ packages: dependency: transitive description: name: lints - sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" + sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" logging: dependency: transitive description: @@ -340,10 +340,10 @@ packages: dependency: transitive description: name: path_provider_android - sha256: "6f01f8e37ec30b07bc424b4deabac37cacb1bc7e2e515ad74486039918a37eb7" + sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a url: "https://pub.dev" source: hosted - version: "2.2.10" + version: "2.2.12" path_provider_foundation: dependency: transitive description: @@ -412,18 +412,18 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: "480ba4345773f56acda9abf5f50bd966f581dac5d514e5fc4a18c62976bbba7e" + sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.3.3" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: c4b35f6cb8f63c147312c054ce7c2254c8066745125264f0c88739c417fc9d9f + sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d" url: "https://pub.dev" source: hosted - version: "2.5.2" + version: "2.5.3" shared_preferences_linux: dependency: transitive description: @@ -561,18 +561,18 @@ packages: dependency: transitive description: name: web - sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.1.0" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.1.0" sdks: dart: ">=3.5.1 <4.0.0" - flutter: ">=3.22.0" + flutter: ">=3.24.0" diff --git a/agrilink_vocpro/pubspec.yaml b/agrilink_vocpro/pubspec.yaml index 8ab1293..0d701b3 100644 --- a/agrilink_vocpro/pubspec.yaml +++ b/agrilink_vocpro/pubspec.yaml @@ -57,7 +57,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^4.0.0 + flutter_lints: ^5.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec